Window creation/X11

From Rosetta Code
Revision as of 09:47, 17 February 2024 by PureFox (talk | contribs) (→‎{{header|Wren}}: Minor tidy)
Task
Window creation/X11
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Create a simple X11 application,   using an X11 protocol library such as Xlib or XCB,   that draws a box and   "Hello World"   in a window.

Implementations of this task should   avoid using a toolkit   as much as possible.

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program creatFenX1164.s   */
/* link with gcc options  -lX11 -L/usr/lpp/X11/lib */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ ClientMessage, 33

/*******************************************/
/* Initialized data                        */
/*******************************************/ 
.data
szRetourligne: .asciz  "\n"
szMessErreur:  .asciz "Server X11 not found.\n"
szMessErrfen:  .asciz "Error create X11 window.\n"

szLibDW:       .asciz "WM_DELETE_WINDOW"      // message close window

/*******************************************/
/* UnInitialized data                      */
/*******************************************/ 
.bss
.align 4
qDisplay:        .skip 8           // Display address
qDefScreen:      .skip 8           // Default screen address
identWin:        .skip 8           // window ident
wmDeleteMessage: .skip 16          // ident close message
stEvent:         .skip 400         // provisional size

buffer:          .skip 500 

/**********************************************/
/* -- Code section                            */
/**********************************************/
.text           
.global main                   // program entry
main:
    mov x0,#0                  // open server X
    bl XOpenDisplay
    cmp x0,#0
    beq erreur
                               //  Ok return Display address
    ldr x1,qAdrqDisplay
    str x0,[x1]                // store Display address for future use
    mov x28,x0                 // and in register 28
                               // load default screen
    ldr x2,[x0,#264]           // at location 264
    ldr x1,qAdrqDefScreen
    str x2,[x1]                //store default_screen
    mov x2,x0
    ldr x0,[x2,#232]           // screen list

                               //screen areas
    ldr x5,[x0,#+88]           // white pixel
    ldr x3,[x0,#+96]           // black pixel
    ldr x4,[x0,#+56]           // bits par pixel
    ldr x1,[x0,#+16]           // root windows
                               // create window x11
    mov x0,x28                 //display
    mov x2,#0                  // position X 
    mov x3,#0                  // position Y
    mov x4,600                 // weight
    mov x5,400                 // height
    mov x6,0                   // bordure ???
    ldr x7,0                   // ?
    ldr x8,qBlanc              // background
    str x8,[sp,-16]!           // argument fot stack
    bl XCreateSimpleWindow
    add sp,sp,16               // for stack alignement
    cmp x0,#0                  // error ?
    beq erreurF
    //mov x3,sp
    ldr x1,qAdridentWin
    str x0,[x1]                // store window ident for future use
    mov x27,x0                 // and in register 27

                               // Correction of window closing error
    mov x0,x28                 // Display address
    ldr x1,qAdrszLibDW         // atom name address
    mov x2,#1                  // False  create atom if not exist
    bl XInternAtom
    cmp x0,#0
    ble erreurF
    ldr x1,qAdrwmDeleteMessage // address message
    str x0,[x1]
    mov x2,x1                  // address atom create
    mov x0,x28                 // display address
    mov x1,x27                 // window ident
    mov x3,#1                  // number of protocoles 
    bl XSetWMProtocols
    cmp x0,#0
    ble erreurF
    
                               // Display window
    mov x1,x27                 // ident window
    mov x0,x28                 // Display address
    bl XMapWindow

1:                             // events loop
    mov x0,x28                 // Display address
    ldr x1,qAdrstEvent         // events structure address
    bl XNextEvent
    ldr x0,qAdrstEvent         // events structure address
    ldr w0,[x0]                // type in 4 fist bytes
    cmp w0,#ClientMessage      // message for close window 
    bne 1b                     // no -> loop

    ldr x0,qAdrstEvent         // events structure address
    ldr x1,[x0,56]             // location message code
    ldr x2,qAdrwmDeleteMessage // equal ?
    ldr x2,[x2]
    cmp x1,x2
    bne 1b                     // no loop 

    mov x0,0                   // end Ok
    b 100f
erreurF:                       // error create window
    ldr x0,qAdrszMessErrfen
    bl affichageMess
    mov x0,1
    b 100f
erreur:                        // error no server x11 active
    ldr x0,qAdrszMessErreur
    bl affichageMess
    mov x0,1
100:                           // program standard end
    mov x8,EXIT
    svc 0 
qBlanc:              .quad 0xF0F0F0F0
qAdrqDisplay:        .quad qDisplay
qAdrqDefScreen:      .quad qDefScreen
qAdridentWin:        .quad identWin
qAdrstEvent:         .quad stEvent
qAdrszMessErrfen:    .quad szMessErrfen
qAdrszMessErreur:    .quad szMessErreur
qAdrwmDeleteMessage: .quad wmDeleteMessage
qAdrszLibDW:         .quad szLibDW
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"

ALGOL 68

Works with: ALGOL 68G version tested with release mk15-0.8b.fc9.i386

Using the X11 & plotutil libraries is not part of any of the original UNESCO/IFIP ALGOL 68 reports. As at December 2008 only ALGOL 68G comes with these built in.

FILE window;
draw device (window, "X", "600x400");
open (window, "Hello, World!", stand draw channel);
  draw erase (window);
  draw move (window, 0.25, 0.5);
  draw colour (window, 1, 0, 0);
  draw text (window, "c", "c", "hello world");
  draw show (window);
  VOID (read char); 
close (window)

ARM Assembly

Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program windows1.s        */

/* compile with as         */
/* link with gcc and options -lX11 -L/usr/lpp/X11/lib   */

/********************************************/
/*Constantes                                */
/********************************************/
.equ STDOUT,              1     @ Linux output console
.equ EXIT,                1     @ Linux syscall
.equ WRITE,               4     @ Linux syscall
/* constantes X11 */
.equ KeyPressed,          2
.equ ButtonPress,         4
.equ MotionNotify,        6
.equ EnterNotify,         7
.equ LeaveNotify,         8
.equ Expose,              12
.equ ClientMessage,       33
.equ KeyPressMask,        1
.equ ButtonPressMask,     4
.equ ButtonReleaseMask,   8
.equ ExposureMask,        1<<15
.equ StructureNotifyMask, 1<<17
.equ EnterWindowMask,     1<<4
.equ LeaveWindowMask,     1<<5 
.equ ConfigureNotify,     22

/*******************************************/
/* DONNEES INITIALISEES                    */
/*******************************************/ 
.data
szWindowName:            .asciz "Windows Raspberry"
szRetourligne:           .asciz  "\n"
szMessDebutPgm:          .asciz "Program start. \n"
szMessErreur:            .asciz "Server X not found.\n"
szMessErrfen:            .asciz "Can not create window.\n"
szMessErreurX11:         .asciz "Error call function X11. \n"
szMessErrGc:             .asciz "Can not create graphics context.\n"
szTitreFenRed:           .asciz "Pi"    
szTexte1:                .asciz "Hello world."
.equ LGTEXTE1, . - szTexte1
szTexte2:                .asciz "Press q for close window or clic X in system menu."
.equ LGTEXTE2, . - szTexte2
szLibDW: .asciz "WM_DELETE_WINDOW"    @ special label for correct close error

/*************************************************/
szMessErr: .ascii	"Error code hexa : "
sHexa: .space 9,' '
         .ascii "  decimal :  "
sDeci: .space 15,' '
         .asciz "\n"

/*******************************************/
/* DONNEES NON INITIALISEES                    */
/*******************************************/ 
.bss
.align 4
ptDisplay:          .skip 4      @ pointer display
ptEcranDef:         .skip 4      @ pointer screen default
ptFenetre:          .skip 4      @ pointer window
ptGC:               .skip 4      @ pointer graphic context
key:                .skip 4      @ key code
wmDeleteMessage:    .skip 8      @ ident close message
event:              .skip 400    @ TODO event size ??
PrpNomFenetre:      .skip 100    @ window name proprety
buffer:             .skip 500 
iWhite:             .skip 4      @ rgb code for white pixel
iBlack:             .skip 4      @ rgb code for black pixel
/**********************************************/
/* -- Code section                            */
/**********************************************/
.text
.global main

main:                               @ entry of program 
    ldr r0,iAdrszMessDebutPgm   @
    bl affichageMess            @ display start message on console linux
    /* attention r6  pointer display*/
    /* attention r8  pointer graphic context   */
    /* attention r9 ident window  */
    /*****************************/
    /*    OPEN SERVER X11        */
    /*****************************/
    mov r0,#0
    bl XOpenDisplay             @ open X server
    cmp r0,#0                   @ error ?
    beq erreurServeur
    ldr r1,iAdrptDisplay
    str r0,[r1]                 @ store display address 
    mov r6,r0                   @ and in register r6
    ldr r2,[r0,#+132]           @ load default_screen
    ldr r1,iAdrptEcranDef
    str r2,[r1]                 @ store default_screen
    mov r2,r0
    ldr r0,[r2,#+140]           @ load pointer screen list
    ldr r5,[r0,#+52]            @ load value white pixel
    ldr r4,iAdrWhite            @ and store in memory
    str r5,[r4]
    ldr r3,[r0,#+56]            @ load value black pixel
    ldr r4,iAdrBlack            @ and store in memory
    str r3,[r4]
    ldr r4,[r0,#+28]            @ load bits par pixel
    ldr r1,[r0,#+8]             @ load root windows
    /**************************/
    /* CREATE WINDOW          */
    /**************************/
    mov r0,r6                   @ address display
    mov r2,#0                   @ window position X
    mov r3,#0                   @ window position Y
    mov r8,#0                   @ for stack alignement
    push {r8}
    push {r3}                   @  background  = black pixel
    push {r5}                   @  border = white pixel
    mov r8,#2                   @  border size
    push {r8}
    mov r8,#400                 @ hauteur
    push {r8}
    mov r8,#600                 @ largeur 
    push {r8}   
    bl XCreateSimpleWindow
    add sp,#24                  @ stack alignement  6 push (4 bytes * 6)
    cmp r0,#0                   @ error ?
    beq erreurF

    ldr r1,iAdrptFenetre
    str r0,[r1]                 @ store window address in memory
    mov r9,r0                   @ and in register r9
    /*****************************/
    /* add window property       */
    /*****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iAdrszWindowName     @ window name
    ldr r3,iAdrszTitreFenRed    @ window name reduced
    mov r4,#0
    push {r4}                   @ parameters not use
    push {r4}
    push {r4}
    push {r4}
    bl XSetStandardProperties
    add sp,sp,#16               @ stack alignement for 4 push
    /**************************************/
    /* for correction window close error  */
    /**************************************/
    mov r0,r6                   @ display address
    ldr r1,iAdrszLibDW          @ atom address
    mov r2,#1                   @ False  créate atom if not exists
    bl XInternAtom
    cmp r0,#0                   @ error X11 ?
    ble erreurX11
    ldr r1,iAdrwmDeleteMessage  @ recept address
    str r0,[r1]
    mov r2,r1                   @ return address
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r3,#1                   @ number of protocols
    bl XSetWMProtocols
    cmp r0,#0                   @ error X11 ?
    ble erreurX11
    /**********************************/
    /*  create graphic context        */
    /**********************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,#0                   @ not use for simply context
    mov r3,#0
    bl XCreateGC
    cmp r0,#0                   @ error ?
    beq erreurGC
    ldr r1,iAdrptGC
    str r0,[r1]                 @ store address graphic context
    mov r8,r0                   @ and in r8
    /****************************/
    /* modif window background  */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iGris1               @ background color
    bl XSetWindowBackground   
    cmp r0,#0                   @ error ?
    ble erreurX11
    /***************************/
    /* OUF!! window display    */
    /***************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    bl XMapWindow
    /****************************/
    /* Write text in the window */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,r8                   @ address graphic context
    mov r3,#50                  @ position x 
    sub sp,#4                   @ stack alignement
    mov r4,#LGTEXTE1  - 1       @ size string 
    push {r4}                   @ on the stack
    ldr r4,iAdrszTexte1            @ string address
    push {r4}
    mov r4,#100                 @ position y 
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement 3 push and 1 stack alignement
    cmp r0,#0                   @ error ?
    blt erreurX11
    /* write text 2 */
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,r8                   @ address graphic context
    mov r3,#10                  @ position x 
    sub sp,#4                   @ stack alignement
    mov r4,#LGTEXTE2  - 1       @ size string 
    push {r4}                   @ on the stack
    ldr r4,iAdrszTexte2            @ string address
    push {r4}
    mov r4,#350                 @ position y 
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement 3 push and 1 stack alignement
    cmp r0,#0                   @ error ?
    blt erreurX11
    /****************************/
    /* Autorisations            */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iFenetreMask         @ autorisation mask
    bl XSelectInput
    cmp r0,#0                   @ error ?
    ble erreurX11
    /****************************/
    /* Events loop              */
    /****************************/
1:
    mov r0,r6                   @ display address
    ldr r1,iAdrevent            @ events address
    bl XNextEvent               @ event ?
    ldr r0,iAdrevent
    ldr r0,[r0]                 @ code event
    cmp r0,#KeyPressed          @ key ?
    bne 2f
    ldr r0,iAdrevent            @ yes read key in buffer
    ldr r1,iAdrbuffer
    mov r2,#255
    ldr r3,iAdrkey
    mov r4,#0
    push {r4}                   @ stack alignement
    push {r4}
    bl XLookupString 
    add sp,#8                   @ stack alignement 2 push
    cmp r0,#1                   @ is character key ?
    bne 2f
    ldr r0,iAdrbuffer           @ yes -> load first buffer character
    ldrb r0,[r0]
    cmp r0,#0x71                @ character q for quit
    beq 5f                      @ yes -> end
    b 4f
2:
    /*                                  */
    /* for example  clic mouse button   */
    /************************************/
    cmp r0,#ButtonPress         @ clic mouse buton
    bne 3f
    ldr r0,iAdrevent
    ldr r1,[r0,#+32]            @ position X mouse clic
    ldr r2,[r0,#+36]            @ position Y
    @ etc for eventuel use
    b 4f
3:
    cmp r0,#ClientMessage       @ code for close window within error
    bne 4f
    ldr r0,iAdrevent
    ldr r1,[r0,#+28]            @ code message address 
    ldr r2,iAdrwmDeleteMessage  @ equal code window créate ???
    ldr r2,[r2]
    cmp r1,r2
    beq 5f                      @ yes -> end window 

4:  @ loop for other event
    b 1b
    /***********************************/
    /* Close window -> free ressources */
    /***********************************/
5:
    mov r0,r6                  @ display address
    ldr r1,iAdrptGC
    ldr r1,[r1]                @ load context graphic address 
    bl XFreeGC
    cmp r0,#0
    blt erreurX11
    mov r0,r6                  @ display address 
    mov r1,r9                  @ window address
    bl XDestroyWindow
    cmp r0,#0
    blt erreurX11
    mov r0,r6                  @ display address
    bl XCloseDisplay
    cmp r0,#0
    blt erreurX11
    mov r0,#0                  @ return code OK
    b 100f
erreurF:   @ create error window but possible not necessary. Display error by server
    ldr r1,iAdrszMessErrfen
    bl   displayError
    mov r0,#1                  @ return error code
    b 100f
erreurGC:                      @ error create graphic context
    ldr r1,iAdrszMessErrGc
    bl   displayError
    mov r0,#1
    b 100f
erreurX11:    @ erreur X11
    ldr r1,iAdrszMessErreurX11
    bl   displayError
    mov r0,#1
    b 100f
erreurServeur:                 @ error no found X11 server see doc putty and Xming
    ldr r1,iAdrszMessErreur
    bl   displayError
    mov r0,#1
    b 100f

100:                           @ standard end of the program 
    mov r7, #EXIT
    svc 0 
iFenetreMask:        .int  KeyPressMask|ButtonPressMask|StructureNotifyMask
iGris1:              .int 0xFFA0A0A0
iAdrWhite:           .int iWhite
iAdrBlack:           .int iBlack
iAdrptDisplay:       .int ptDisplay
iAdrptEcranDef:      .int ptEcranDef
iAdrptFenetre:       .int ptFenetre
iAdrptGC:            .int ptGC
iAdrevent:           .int event
iAdrbuffer:          .int buffer
iAdrkey:             .int key
iAdrszLibDW:         .int szLibDW
iAdrszMessDebutPgm:  .int szMessDebutPgm
iAdrszMessErreurX11: .int szMessErreurX11
iAdrszMessErrGc:     .int szMessErrGc
iAdrszMessErreur:    .int szMessErreur
iAdrszMessErrfen:    .int szMessErrfen
iAdrszWindowName:    .int szWindowName
iAdrszTitreFenRed:   .int szTitreFenRed
iAdrszTexte1:        .int szTexte1
iAdrszTexte2:        .int szTexte2
iAdrPrpNomFenetre:   .int PrpNomFenetre
iAdrwmDeleteMessage: .int wmDeleteMessage
/******************************************************************/
/*     display text with size calculation                         */ 
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    mov r2,#0                               @ counter length 
1:                                          @ loop length calculation 
    ldrb r1,[r0,r2]                         @ read octet start position + index 
    cmp r1,#0                               @ if 0 its over 
    addne r2,r2,#1                          @ else add 1 in the length 
    bne 1b                                  @ and loop 
                                            @ so here r2 contains the length of the message 
    mov r1,r0                               @ address message in r1 
    mov r0,#STDOUT                          @ code to write to the standard output Linux 
    mov r7, #WRITE                          @ code call system "write" 
    svc #0                                  @ call systeme 
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */ 
    bx lr                                   @ return
/***************************************************/
/*   affichage message d erreur              */
/***************************************************/
/* r0 contains error code  r1 : message address */
displayError:
    push {r0-r2,lr}                         @ save registers
    mov r2,r0                               @ save error code
    mov r0,r1
    bl affichageMess
    mov r0,r2                               @ error code
    ldr r1,iAdrsHexa
    bl conversion16                         @ conversion hexa
    mov r0,r2                               @ error code
    ldr r1,iAdrsDeci                        @ result address
    bl conversion10                         @ conversion decimale
    ldr r0,iAdrszMessErr                    @ display error message
    bl affichageMess
100:
    pop {r0-r2,lr}                          @ restaur registers
    bx lr                                   @ return 
iAdrszMessErr:                 .int szMessErr
iAdrsHexa:                     .int sHexa
iAdrsDeci:                     .int sDeci
/******************************************************************/
/*     Converting a register to hexadecimal                      */ 
/******************************************************************/
/* r0 contains value and r1 address area   */
conversion16:
    push {r1-r4,lr}                                    @ save registers
    mov r2,#28                                         @ start bit position
    mov r4,#0xF0000000                                 @ mask
    mov r3,r0                                          @ save entry value
1:                                                     @ start loop
    and r0,r3,r4                                       @value register and mask
    lsr r0,r2                                          @ move right 
    cmp r0,#10                                         @ compare value
    addlt r0,#48                                       @ <10  ->digit	
    addge r0,#55                                       @ >10  ->letter A-F
    strb r0,[r1],#1                                    @ store digit on area and + 1 in area address
    lsr r4,#4                                          @ shift mask 4 positions
    subs r2,#4                                         @  counter bits - 4 <= zero  ?
    bge 1b                                             @  no -> loop

100:
    pop {r1-r4,lr}                                     @ restaur registers 
    bx lr                                              @return
/******************************************************************/
/*     Converting a register to a decimal unsigned                */ 
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                 @ save registers 
    mov r3,r1
    mov r2,#LGZONECAL
1:                                                  @ start loop
    bl divisionpar10U                               @ unsigned  r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                                      @ digit
    strb r1,[r3,r2]                                 @ store digit on area
    cmp r0,#0                                       @ stop if quotient = 0 
    subne r2,#1                                     @ else previous position
    bne 1b                                          @ and loop
                                                    @ and move digit from left of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]
    add r2,#1
    add r4,#1
    cmp r2,#LGZONECAL
    ble 2b
                                                      @ and move spaces in end on area
    mov r0,r4                                         @ result length 
    mov r1,#' '                                       @ space
3:
    strb r1,[r3,r4]                                   @ store space in area
    add r4,#1                                         @ next position
    cmp r4,#LGZONECAL
    ble 3b                                            @ loop if r4 <= area size
 
100:
    pop {r1-r4,lr}                                    @ restaur registres 
    bx lr                                             @return
 
/***************************************************/
/*   division par 10   unsigned                    */
/***************************************************/
/* r0 dividende   */
/* r0 quotient    */
/* r1 remainder   */
divisionpar10U:
    push {r2,r3,r4, lr}
    mov r4,r0                                          @ save value
    ldr r3,iMagicNumber                                @ r3 <- magic_number    raspberry 1 2
    umull r1, r2, r3, r0                               @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0) 
    mov r0, r2, LSR #3                                 @ r2 <- r2 >> shift 3
    add r2,r0,r0, lsl #2                               @ r2 <- r0 * 5 
    sub r1,r4,r2, lsl #1                               @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2,r3,r4,lr}
    bx lr                                              @ leave function 
iMagicNumber:  	.int 0xCCCCCCCD


BaCon

'--- added a flush to exit cleanly   
PRAGMA LDFLAGS `pkg-config --cflags --libs x11`
PRAGMA INCLUDE <X11/Xlib.h>
PRAGMA INCLUDE <X11/Xutil.h>

OPTION PARSE FALSE
 
'---XLIB is so ugly
ALIAS XNextEvent TO EVENT
ALIAS XOpenDisplay TO DISPLAY
ALIAS DefaultScreen TO SCREEN
ALIAS XCreateSimpleWindow TO CREATE
ALIAS XCloseDisplay TO CLOSE_DISPLAY
ALIAS XSelectInput TO EVENT_TYPE
ALIAS XMapWindow TO MAP_EVENT
ALIAS XFillRectangle TO FILL_RECTANGLE
ALIAS XDrawString TO DRAW_STRING
ALIAS XFlush TO FLUSH

 
'---pointer to X Display structure
DECLARE d TYPE  Display*
 
'---pointer to the newly created window		
'DECLARE w TYPE WINDOW
 
'---pointer to the XEvent
DECLARE e TYPE XEvent
 
DECLARE msg TYPE char*
 
'--- number of screen to place the window on
DECLARE s TYPE int
 
 
 
  msg = "Hello, World!"
 
 
   d = DISPLAY(NULL)
   IF d == NULL THEN
	 EPRINT "Cannot open display" FORMAT "%s%s\n"
	 END
   END IF
 
   s = SCREEN(d)
   w = CREATE(d, RootWindow(d, s), 10, 10, 100, 100, 1,BlackPixel(d, s), WhitePixel(d, s))
 
   EVENT_TYPE(d, w, ExposureMask | KeyPressMask)
   MAP_EVENT(d, w)
 
   WHILE  (1) 
	 EVENT(d, &e)
	 IF e.type == Expose THEN
	    FILL_RECTANGLE(d, w, DefaultGC(d, s), 20, 20, 10, 10)
	    DRAW_STRING(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg))
	 END IF
	 IF e.type == KeyPress THEN
	    BREAK
	 END IF   
   WEND
   FLUSH(d)
   CLOSE_DISPLAY(d)

C

Xlib

Library: Xlib

Compile with:

  • gcc hello-x.c -L/usr/X11R6/lib -lX11 -o hello-x
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
   Display *d;
   Window w;
   XEvent e;
   const char *msg = "Hello, World!";
   int s;

   d = XOpenDisplay(NULL);
   if (d == NULL) {
      fprintf(stderr, "Cannot open display\n");
      exit(1);
   }

   s = DefaultScreen(d);
   w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
                           BlackPixel(d, s), WhitePixel(d, s));
   XSelectInput(d, w, ExposureMask | KeyPressMask);
   XMapWindow(d, w);

   while (1) {
      XNextEvent(d, &e);
      if (e.type == Expose) {
         XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
         XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
      }
      if (e.type == KeyPress)
         break;
   }

   XCloseDisplay(d);
   return 0;
}

XCB

Library: XCB

Compile with:

  • gcc -o helloxcb helloxcb.c -lxcb
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <xcb/xcb.h>

int main ()
{
  xcb_connection_t    *c;
  xcb_screen_t        *screen;
  xcb_drawable_t       win;
  xcb_gcontext_t       foreground;
  xcb_gcontext_t       background;
  xcb_generic_event_t *e;
  uint32_t             mask = 0;
  uint32_t             values[2];

  char string[] = "Hello, XCB!";
  uint8_t string_len = strlen(string);

  xcb_rectangle_t rectangles[] = {
    {40, 40, 20, 20},
  };

  c = xcb_connect (NULL, NULL);

  /* get the first screen */
  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;

  /* root window */
  win = screen->root;

  /* create black (foreground) graphic context */
  foreground = xcb_generate_id (c);
  mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
  values[0] = screen->black_pixel;
  values[1] = 0;
  xcb_create_gc (c, foreground, win, mask, values);

  /* create white (background) graphic context */
  background = xcb_generate_id (c);
  mask = XCB_GC_BACKGROUND | XCB_GC_GRAPHICS_EXPOSURES;
  values[0] = screen->white_pixel;
  values[1] = 0;
  xcb_create_gc (c, background, win, mask, values);

  /* create the window */
  win = xcb_generate_id(c);
  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
  values[0] = screen->white_pixel;
  values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
  xcb_create_window (c,                             /* connection    */
                     XCB_COPY_FROM_PARENT,          /* depth         */
                     win,                           /* window Id     */
                     screen->root,                  /* parent window */
                     0, 0,                          /* x, y          */
                     150, 150,                      /* width, height */
                     10,                            /* border_width  */
                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class         */
                     screen->root_visual,           /* visual        */
                     mask, values);                 /* masks         */

  /* map the window on the screen */
  xcb_map_window (c, win);

  xcb_flush (c);

  while ((e = xcb_wait_for_event (c))) {
    switch (e->response_type & ~0x80) {
    case XCB_EXPOSE:
      xcb_poly_rectangle (c, win, foreground, 1, rectangles);
      xcb_image_text_8 (c, string_len, win, background, 20, 20, string);
      xcb_flush (c);
      break;
    case XCB_KEY_PRESS:
      goto endloop;
    }
    free (e);
  }
  endloop:

  return 0;
}

COBOL

Tested with GnuCOBOL, and only on 64bit architecture, GNU/Linux. Nods to the C XLib version.

       identification division.
       program-id. x11-hello.
       installation. cobc -x x11-hello.cob -lX11
       remarks. Use of private data is likely not cross platform.

       data division.
       working-storage section.
       01 msg.
          05 filler            value z"S'up, Earth?".
       01 msg-len              usage binary-long value 12.

       01 x-display            usage pointer.
       01 x-window             usage binary-c-long.

      *> GnuCOBOL does not evaluate C macros, need to peek at opaque
      *> data from Xlib.h
      *> some padding is added, due to this comment in the header
      *> "there is more to this structure, but it is private to Xlib"
       01 x-display-private    based.
          05 x-ext-data        usage pointer sync.
          05 private1          usage pointer.
          05 x-fd              usage binary-long.
          05 private2          usage binary-long.
          05 proto-major-version   usage binary-long.
          05 proto-minor-version   usage binary-long.
          05 vendor            usage pointer sync.
          05 private3          usage pointer.
          05 private4          usage pointer.
          05 private5          usage pointer.
          05 private6          usage binary-long.
          05 allocator         usage program-pointer sync.
          05 byte-order        usage binary-long.
          05 bitmap-unit       usage binary-long.
          05 bitmap-pad        usage binary-long.
          05 bitmap-bit-order  usage binary-long.
          05 nformats          usage binary-long.
          05 screen-format     usage pointer sync.
          05 private8          usage binary-long.
          05 x-release         usage binary-long.
          05 private9          usage pointer sync.
          05 private10         usage pointer sync.
          05 qlen              usage binary-long.
          05 last-request-read usage binary-c-long unsigned sync.
          05 request           usage binary-c-long unsigned sync.
          05 private11         usage pointer sync.
          05 private12         usage pointer.
          05 private13         usage pointer.
          05 private14         usage pointer.
          05 max-request-size  usage binary-long unsigned.
          05 x-db              usage pointer sync.
          05 private15         usage program-pointer sync.
          05 display-name      usage pointer.
          05 default-screen    usage binary-long.
          05 nscreens          usage binary-long.
          05 screens           usage pointer sync.
          05 motion-buffer     usage binary-c-long unsigned.
          05 private16         usage binary-c-long unsigned.
          05 min-keycode       usage binary-long.
          05 max-keycode       usage binary-long.
          05 private17         usage pointer sync.
          05 private18         usage pointer.
          05 private19         usage binary-long.
          05 x-defaults        usage pointer sync.
          05 filler            pic x(256).

       01 x-screen-private     based.
          05 scr-ext-data      usage pointer sync.
          05 display-back      usage pointer.
          05 root              usage binary-c-long.
          05 x-width           usage binary-long.
          05 x-height          usage binary-long.
          05 m-width           usage binary-long.
          05 m-height          usage binary-long.
          05 x-ndepths         usage binary-long.
          05 depths            usage pointer sync.
          05 root-depth        usage binary-long.
          05 root-visual       usage pointer sync.
          05 default-gc        usage pointer.
          05 cmap              usage pointer.
          05 white-pixel       usage binary-c-long unsigned sync.
          05 black-pixel       usage binary-c-long unsigned.
          05 max-maps          usage binary-long.
          05 min-maps          usage binary-long.
          05 backing-store     usage binary-long.
          05 save_unders       usage binary-char.
          05 root-input-mask   usage binary-c-long sync.
          05 filler            pic x(256).

       01 event.
          05 e-type usage      binary-long.
          05 filler            pic x(188).
          05 filler            pic x(256).
       01 Expose               constant as 12.
       01 KeyPress             constant as 2.

      *> ExposureMask or-ed with KeyPressMask, from X.h
       01 event-mask           usage binary-c-long value 32769.

      *> make the box around the message wide enough for the font
       01 x-char-struct.
          05 lbearing          usage binary-short.
          05 rbearing          usage binary-short.
          05 string-width      usage binary-short.
          05 ascent            usage binary-short.
          05 descent           usage binary-short.
          05 attributes        usage binary-short unsigned.
       01 font-direction       usage binary-long.
       01 font-ascent          usage binary-long.
       01 font-descent         usage binary-long.

       01 XGContext            usage binary-c-long.
       01 box-width            usage binary-long.
       01 box-height           usage binary-long.

      *> ***************************************************************
       procedure division.

       call "XOpenDisplay" using by reference null returning x-display
           on exception
               display function module-id " Error: "
                       "no XOpenDisplay linkage, requires libX11"
                  upon syserr
               stop run returning 1
       end-call
       if x-display equal null then
           display function module-id " Error: "
                   "XOpenDisplay returned null" upon syserr
           stop run returning 1
       end-if
       set address of x-display-private to x-display

       if screens equal null then
           display function module-id " Error: "
                   "XOpenDisplay associated screen null" upon syserr
           stop run returning 1
       end-if
       set address of x-screen-private to screens

       call "XCreateSimpleWindow" using
           by value x-display root 10 10 200 50 1
                    black-pixel white-pixel
           returning x-window
       call "XStoreName" using
           by value x-display x-window by reference msg

       call "XSelectInput" using by value x-display x-window event-mask

       call "XMapWindow" using by value x-display x-window

       call "XGContextFromGC" using by value default-gc
           returning XGContext
       call "XQueryTextExtents" using by value x-display XGContext
           by reference msg by value msg-len
           by reference font-direction font-ascent font-descent
           x-char-struct
       compute box-width = string-width + 8
       compute box-height = font-ascent + font-descent + 8

       perform forever
          call "XNextEvent" using by value x-display by reference event
          if e-type equal Expose then
              call "XDrawRectangle" using
                  by value x-display x-window default-gc 5 5
                           box-width box-height
              call "XDrawString" using
                  by value x-display x-window default-gc 10 20
                  by reference msg by value msg-len
          end-if
          if e-type equal KeyPress then exit perform end-if
       end-perform

       call "XCloseDisplay" using by value x-display

       goback.
       end program x11-hello.

Common Lisp

This example needs review by someone who knows about: X11
This example was written in near-total ignorance of X11 by consulting the CLX manual to find equivalents for the parts of the C example. It was also only tested with Mac OS X X11, which is not exactly normal. — (ps: Testing on Linux (Fedora 21/x86-64), it seems to display black-on-black, so the "Hello" is lost.). Testing new code changes (i.e. adding background and foreground) should fix the issue, it was tested on LinuxMint 17.1/x86-64. Also tested on Debian; with a minor change on the text position it creates a pixel perfect replica of the C example. Could this warning be removed then?

If you know X11, please review this example and, as necessary, improve it or describe what should be done for someone who knows the language.

Translation of: C
Library: CLX

This example uses CLX, which is the de facto standard X11 library for Common Lisp. CLX is not a binding to Xlib; it is a Lisp library implementing the X11 protocol.

;;; Single-file/interactive setup; large applications should define an ASDF system instead

(let* ((display (open-default-display))
       (screen (display-default-screen display))
       (root-window (screen-root screen))
       (black-pixel (screen-black-pixel screen))
       (white-pixel (screen-white-pixel screen))
       (window (create-window :parent root-window
                              :x 10 :y 10
                              :width 100 :height 100
                              :background white-pixel
                              :event-mask '(:exposure :key-press)))
       (gc (create-gcontext :drawable window
                            :foreground black-pixel
                            :background white-pixel)))
  (map-window window)
  (unwind-protect
       (event-case (display :discard-p t)
         (exposure ()
                   (draw-rectangle window gc 20 20 10 10 t)
                   (draw-glyphs window gc 10 50 "Hello, World!")
                   nil #| continue receiving events |#)
         (key-press ()
                    t #| non-nil result signals event-case to exit |#))
    (when window
      (destroy-window window))
    (when gc
      (free-gcontext gc))
    (close-display display)))

Forth

Running Ubuntu 20.04 64-bit Using  : Gforth 0.7.9_20211014

warnings off
require xlib.fs

0 value 	X11-D                 \ Display
0 value		X11-S                 \ Screen
0 value 	X11-root
0 value 	X11-GC
0 value 	X11-W                 \ Window
0 value 	X11-Black
0 value         X11-White
9 value 	X11-Top
0 value 	X11-Left
create 		X11-ev 96 allot

variable 	wm_delete

: X11-D-S 	X11-D X11-S ;
: X11-D-G       X11-D X11-GC ;
: X11-D-W 	X11-D X11-W ;
: X11-D-W-G     X11-D-W X11-GC ;

: open-X11 ( -- )
	X11-D 0= if 0 XOpendisplay to X11-D
		    X11-D    0= abort" can't connect to X server"
		    X11-D    XDefaultscreen to X11-S
		    X11-D-S  XRootwindow to X11-root
		    X11-D-S  XDefaultGC to X11-GC
		    X11-D-S  XBlackPixel to X11-Black
		    X11-D-S  XWhitePixel to X11-White
		then
	X11-W 0= if X11-D    X11-root X11-top X11-left 400 220  0 0 $808080 XCreateSimplewindow to X11-W
		    X11-W    0= abort" failed to create X11-window"
		    X11-D-W  $28043 XSelectInput drop 
		    X11-D    s" WM_DELETE_WEINDOW" 1 XInternAtom wm_delete !
	            X11-D-W  wm_delete 1 XSetWMProtocols drop
		    X11-D-W  XMapwindow drop
		    X11-D    XFlush drop
		then ;

: close-graphics ( -- )
	X11-W if X11-D-W   XDestroywindow drop  0 to X11-W
	      then
        X11-D if X11-D     XClosedisplay  0 to X11-D
	      then ;

: foreground  	>r X11-D-G r> XSetForeground drop ;
: background  	>r X11-D-G r> XSetBackground drop ;
: keysym      	X11-ev     0 XLookupKeysym ;

: ev-loop
        begin X11-D X11-ev XNextEvent throw
	      X11-White    foreground
	      X11-Black    background
	      X11-D-W-G    100 100   s" Hello World" XDrawString drop
	      X11-D-W-G    100 120 150 25 XDrawRectangle drop
	      X11-D-W-G    110 135   s" Press ESC to exit ..." XDrawString drop
	      case X11-ev  @ $ffffffff and
	           3 of keysym XK_Escape = if exit then endof
	      endcase
	again ;
\ #### Test ##### 
0  open-X11
ev-loop
close-graphics
bye

Go

Translation of: C
package main

// Copyright (c) 2013 Alex Kesling
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import (
    "log"
    "github.com/jezek/xgb"
    "github.com/jezek/xgb/xproto"
)

func main() {
    // Open the connection to the X server
    X, err := xgb.NewConn()
    if err != nil {
        log.Fatal(err)
    }

    // geometric objects
    points := []xproto.Point{
        {10, 10},
        {10, 20},
        {20, 10},
        {20, 20}};

    polyline := []xproto.Point{
        {50, 10},
        { 5, 20},     // rest of points are relative
        {25,-20},
        {10, 10}};

    segments := []xproto.Segment{
        {100, 10, 140, 30},
        {110, 25, 130, 60}};

    rectangles := []xproto.Rectangle{
        { 10, 50, 40, 20},
        { 80, 50, 10, 40}};

    arcs := []xproto.Arc{
        {10, 100, 60, 40, 0, 90 << 6},
        {90, 100, 55, 40, 0, 270 << 6}};

    setup := xproto.Setup(X)
    // Get the first screen
    screen := setup.DefaultScreen(X)

    // Create black (foreground) graphic context
    foreground, _ := xproto.NewGcontextId(X)
    mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures)
    values := []uint32{screen.BlackPixel, 0}
    xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values)

    // Ask for our window's Id
    win, _ := xproto.NewWindowId(X)
    winDrawable := xproto.Drawable(win)

    // Create the window
    mask = uint32(xproto.CwBackPixel | xproto.CwEventMask)
    values = []uint32{screen.WhitePixel, xproto.EventMaskExposure}
    xproto.CreateWindow(X,                  // Connection
            screen.RootDepth,               // Depth
            win,                            // Window Id
            screen.Root,                    // Parent Window
            0, 0,                           // x, y
            150, 150,                       // width, height
            10,                             // border_width
            xproto.WindowClassInputOutput,  // class
            screen.RootVisual,              // visual
            mask, values)                   // masks

    // Map the window on the screen
    xproto.MapWindow(X, win)

    for {
        evt, err := X.WaitForEvent()
        switch evt.(type) {
            case xproto.ExposeEvent:
                /* We draw the points */
                xproto.PolyPoint(X, xproto.CoordModeOrigin, winDrawable, foreground, points)

                /* We draw the polygonal line */
                xproto.PolyLine(X, xproto.CoordModePrevious, winDrawable, foreground, polyline)

                /* We draw the segments */
                xproto.PolySegment(X, winDrawable, foreground, segments)

                /* We draw the rectangles */
                xproto.PolyRectangle(X, winDrawable, foreground, rectangles)

                /* We draw the arcs */
                xproto.PolyArc(X, winDrawable, foreground, arcs)

            default:
                /* Unknown event type, ignore it */
        }

        if err != nil {
            log.Fatal(err)
        }
    }
    return
}

Screen capture:

Groovy

Run:

groovy WindowCreation.groovy
import javax.swing.*
import java.awt.*
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import java.awt.geom.Rectangle2D

class WindowCreation extends JApplet implements Runnable {
    void paint(Graphics g) {
        (g as Graphics2D).with {
            setStroke(new BasicStroke(2.0f))
            drawString("Hello Groovy!", 20, 20)
            setPaint(Color.blue)
            draw(new Rectangle2D.Double(10d, 50d, 30d, 30d))
        }
    }

    void run() {
        new JFrame("Groovy Window Demo").with {
            addWindowListener(new WindowAdapter() {
                void windowClosing(WindowEvent e) {
                    System.exit(0)
                }
            })

            getContentPane().add("Center", new WindowCreation())
            pack()
            setSize(new Dimension(150, 150))
            setVisible(true)
        }
    }
}

GUISS

Graphical User Interface Support Script is really a language for operating a computer, rather than programming one, so we cannot do this via X11 libraries. The example uses leafpad for our open window, and the box symbols to enclose our text:

Start,Programs,Applications,Editors,Leafpad,Textbox,
Type:[openbox]Hello World[pling][closebox]

Haskell

Using

Library: X11

from HackageDB

import Graphics.X11.Xlib
import Control.Concurrent (threadDelay)

main = do
  display <- openDisplay ""
  let defScr = defaultScreen display
  rw <- rootWindow display defScr

  xwin <- createSimpleWindow display rw
      0 0 400 200 1
      (blackPixel display defScr)
      (whitePixel display defScr)

  setTextProperty display xwin "Rosetta Code: X11 simple window" wM_NAME

  mapWindow display xwin

  sync display False
  threadDelay (5000000)

  destroyWindow display xwin
  closeDisplay display

Icon and Unicon

Icon and Unicon provide a portable graphics implementation that does not rely upon a toolkit. The intent is to be platform independent and the same code runs on multiple platforms without change and producing results with only minor variations. Icon and Unicon graphics are implemented in X-Windows as well as MS-Windows and others. There are additional 3D graphics capabilities implemented using opengl.

procedure main()
   W1 := open("X-Window","g","size=250,250","bg=black","fg=red") | stop("unable to open window")
   FillRectangle(W1,50,50,150,150)
   WDone(W1)
end

link graphics

graphics.icn provides graphics

Additionally, the WOpen procedure and Window.App methods are available.

Java

Library: Java

compile

javac WindowExample.java

run

java WindowExample
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class WindowExample {

  public static void main(String[] args) {
    Runnable runnable = new Runnable() {
      public void run() {
	createAndShow();
      }
    };
    SwingUtilities.invokeLater(runnable);
  }
	
  static void createAndShow() {
    JFrame frame = new JFrame("Hello World");
    frame.setSize(640,480);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}

The previous example works but doesn't write any text or draw any box; the following does both.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class WindowExample extends JApplet {
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

        g2.setStroke(new BasicStroke(2.0f));
        g2.drawString("Hello java", 20, 20);
        g2.setPaint(Color.blue);
        g2.draw(new Rectangle2D.Double(40, 40, 20, 20));
    }

    public static void main(String s[]) {
        JFrame f = new JFrame("ShapesDemo2D");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        JApplet applet = new ShapesDemo2D();
        f.getContentPane().add("Center", applet);
        f.pack();
        f.setSize(new Dimension(150, 150));
        f.setVisible(true);
    }
}

Julia

This was based on https://en.wikipedia.org/wiki/Xlib, and mostly quoted from from the XLib.jl test2() testing code function.

using Xlib

function x11demo()
    # Open connection to the server.
    dpy = XOpenDisplay(C_NULL)
    dpy == C_NULL && error("unable to open display")
    scr = DefaultScreen(dpy)

    # Create a window.
    win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 10, 10, 300, 100, 1,
                              BlackPixel(dpy, scr), WhitePixel(dpy, scr))

    # Select the kind of events we are interested in.
    XSelectInput(dpy, win, ExposureMask | KeyPressMask)

    # Show or in x11 terms map window.
    XMapWindow(dpy, win)

    # Run event loop.
    evt = Ref(XEvent())
    while true
        XNextEvent(dpy, evt)

        # Draw or redraw the window.
        if EventType(evt) == Expose
            XFillRectangle(dpy, win, DefaultGC(dpy, scr), 24, 24, 16, 16)
            XDrawString(dpy, win, DefaultGC(dpy, scr), 50, 50, "Hello, World! Press any key to exit.")
        end

        # Exit whenever a key is pressed.
        if EventType(evt) == KeyPress
            break
        end
    end

    # Shutdown server connection
    XCloseDisplay(dpy)
end

x11demo()

Kotlin

Translation of: C
Library: Xlib
// Kotlin Native v0.3

import kotlinx.cinterop.*
import Xlib.*

fun main(args: Array<String>) {
    val msg = "Hello, World!"
    val d = XOpenDisplay(null)
    if (d == null) {
        println("Cannot open display")
        return
    }

    val s = XDefaultScreen(d)
    val w = XCreateSimpleWindow(d, XRootWindow(d, s), 10, 10, 160, 160, 1,
                                XBlackPixel(d, s), XWhitePixel(d, s))
    XSelectInput(d, w, ExposureMask or KeyPressMask)
    XMapWindow(d, w)
    val e = nativeHeap.alloc<XEvent>()
    
    while (true) {
        XNextEvent(d, e.ptr)
        if (e.type == Expose) {
            XFillRectangle(d, w, XDefaultGC(d, s), 55, 40, 50, 50)
            XDrawString(d, w, XDefaultGC(d, s), 45, 120, msg, msg.length)
        }
        else if (e.type == KeyPress) break
    }

    XCloseDisplay(d)
    nativeHeap.free(e)
}

M2000 Interpreter

M2000 interpteter is a Visual Basic 6 (vb6) gui application, so we can't use X11. When we use Wine, connecting to X11 may occur but this is invisible for interpreter scope.

Ao for this task we use the M2000 way to make a form and do something on it.

\\ M2000 froms (windows) based on a flat, empty with no title bar, vb6 window and a user control.
\\ title bar is a user control in M2000 form
\\ On linux, wine application run M2000 interpreter traslating vb6 calls to window system.
Module SquareAndText2Window {
	Const black=0, white=15
	Declare form1 form
	\\ defaultwindow  title is the name of variable,here is: form1 
	Rem With form1, "Title",  "A title for this window"
	Method form1,"move", 2000,3000,10000,8000  ' in twips
	layer form1 {
		Cls white
		Font "Verdana"
		Rem Window 12 , 10000,8000;  ' hide modr 13 using a REM before
		Rem 
		Mode 12    ' 12 in pt
		Cls white,  2      ' fill white, set third raw for top of scrolling frame
		Pen  black
		Move 1000,2000  ' absolute coordinated in twips - use Step for relative coordinates
		\\ polygon use relative coordinates in twips
		polygon white, 1000,0,0,-1000,-1000,0,0,-1000
		\\ write text using graphic coordinates
		Move 1000, 3000 : Legend "Hello World", "Arial", 12
		\\ write text using layer as console (font Verdana)
		Print @(15,5),"Goodbye Wolrd"
		\\ 9120  7920 if we use window 12,10000, 8000 (cut exactly for console use)
		\\ 10000 8000 if we use Mode 12
		\\ scale.y include window height (including header)
		\\ the layer extend bellow 
		Print scale.x, scale.y 
	}
	\\ show form1 modal (continue to next line when we close the window)
	Method form1,"Show", 1
	\\ closing meand hide in M2000
	wait 1000  ' in msec
	Method form1,"move", random(2000, 10000),random(3000, 8000)
	\\ now show again
	Method form1,"Show", 1
	\\ now we close the form, releasing resources
	Declare form1 Nothing
}
SquareAndText2Window

Mathematica /Wolfram Language

Note that GUIKit is a high-level wrapper for Swing.

Needs["GUIKit`"]
 ref = GUIRun[Widget["Panel", {
    Widget[
     "ImageLabel", {"data" -> 
       Script[ExportString[Graphics[Rectangle[{0, 0}, {1, 1}]], 
         "GIF"]]}],
    Widget["Label", { "text" -> "Hello World!"}]}
   ]]

Nim

import x11/[xlib,xutil,x]

const
  windowWidth = 1000
  windowHeight = 600
  borderWidth = 5
  eventMask = ButtonPressMask or KeyPressMask or ExposureMask

var
  display: PDisplay
  window: Window
  deleteMessage: Atom
  graphicsContext: GC

proc init() =
  display = XOpenDisplay(nil)
  if display == nil:
    quit "Failed to open display"

  let
    screen = XDefaultScreen(display)
    rootWindow = XRootWindow(display, screen)
    foregroundColor = XBlackPixel(display, screen)
    backgroundColor = XWhitePixel(display, screen)

  window = XCreateSimpleWindow(display, rootWindow, -1, -1, windowWidth,
      windowHeight, borderWidth, foregroundColor, backgroundColor)

  discard XSetStandardProperties(display, window, "X11 Example", "window", 0,
      nil, 0, nil)

  discard XSelectInput(display, window, eventMask)
  discard XMapWindow(display, window)

  deleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false.XBool)
  discard XSetWMProtocols(display, window, deleteMessage.addr, 1)

  graphicsContext = XDefaultGC(display, screen)


proc drawWindow() =
  const text = "Hello, Nim programmers."
  discard XDrawString(display, window, graphicsContext, 10, 50, text, text.len)
  discard XFillRectangle(display, window, graphicsContext, 20, 20, 10, 10)


proc mainLoop() =
  ## Process events until the quit event is received
  var event: XEvent
  while true:
    discard XNextEvent(display, event.addr)
    case event.theType
    of Expose:
      drawWindow()
    of ClientMessage:
      if cast[Atom](event.xclient.data.l[0]) == deleteMessage:
        break
    of KeyPress:
      let key = XLookupKeysym(cast[PXKeyEvent](event.addr), 0)
      if key != 0:
        echo "Key ", key, " pressed"
    of ButtonPressMask:
      echo "Mouse button ", event.xbutton.button, " pressed at ",
          event.xbutton.x, ",", event.xbutton.y
    else:
      discard


proc main() =
  init()
  mainLoop()
  discard XDestroyWindow(display, window)
  discard XCloseDisplay(display)


main()

OCaml

Library: OCaml-Xlib

execute as a script with:

ocaml -I +Xlib Xlib.cma script.ml

or compile to native code:

ocamlopt -I +Xlib Xlib.cmxa prog.ml -o prog

or to make a standalone script add these lines at the beginning of the file:

#!/usr/bin/env ocaml
#directory "+Xlib"
#load "Xlib.cma"
open Xlib

let () =
  let d = xOpenDisplay "" in
  let s = xDefaultScreen d in
  let w = xCreateSimpleWindow d (xRootWindow d s) 10 10 100 100 1
                                (xBlackPixel d s) (xWhitePixel d s) in
  xSelectInput d w [ExposureMask; KeyPressMask];
  xMapWindow d w;

  let msg = "Hello, World!" in

  let rec main_loop() =
    match xEventType(xNextEventFun d) with
    | Expose ->
        xFillRectangle d w (xDefaultGC d s) 20 20 10 10;
        xDrawString d w (xDefaultGC d s) 10 50 msg;
        main_loop()
    | KeyPress -> ()  (* exit main loop *)
    | _ -> main_loop()
  in
  main_loop();
  xCloseDisplay d;
;;

Pascal

Translation of: C

from wiki.freepascal.org/X11#Examples. Compiled with Freepascal 2.6.4-32

program xshowwindow;
{$mode objfpc}{$H+}

uses
  xlib, x, ctypes;
 
procedure ModalShowX11Window(AMsg: string);
var
  d: PDisplay;
  w: TWindow;
  e: TXEvent;
  msg: PChar;
  s: cint;
begin
  msg := PChar(AMsg);
 
  { open connection with the server }
  d := XOpenDisplay(nil);
  if (d = nil) then
  begin
    WriteLn('[ModalShowX11Window] Cannot open display');
    exit;
  end;
  s := DefaultScreen(d);
 
  { create window }
  w := XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 50, 1,
                           BlackPixel(d, s), WhitePixel(d, s));
 
  { select kind of events we are interested in }
  XSelectInput(d, w, ExposureMask or KeyPressMask);
 
  { map (show) the window }
  XMapWindow(d, w);
 
  { event loop }
  while (True) do
  begin
    XNextEvent(d, @e);
    { draw or redraw the window }
    if (e._type = Expose) then
    begin
      XFillRectangle(d, w, DefaultGC(d, s), 0, 10, 100, 3);
      XFillRectangle(d, w, DefaultGC(d, s), 0, 30, 100, 3);      
      XDrawString   (d, w, DefaultGC(d, s), 5, 25, msg, strlen(msg));
    end;
    { exit on key press }
    if (e._type = KeyPress) then Break;
  end;
 
  { close connection to server }
  XCloseDisplay(d);
end;
 
begin
  ModalShowX11Window('Hello, World!');
end.

Perl

X11::Protocol

#!/usr/bin/perl -w
use strict;
use X11::Protocol;

my $X = X11::Protocol->new;

my $window = $X->new_rsrc;
$X->CreateWindow ($window,
                  $X->root,         # parent window
                  'InputOutput',    # class
                  0,                # depth, copy from parent
                  0,                # visual, copy from parent
                  0,0,              # X,Y (window manager will override)
                  300,100,          # width,height
                  0,                # border width
                  background_pixel => $X->black_pixel,
                  event_mask       => $X->pack_event_mask('Exposure',
                                                          'ButtonPress'),
                 );

my $gc = $X->new_rsrc;
$X->CreateGC ($gc, $window,
              foreground => $X->white_pixel);

$X->{'event_handler'} = sub {
  my %event = @_;
  my $event_name = $event{'name'};

  if ($event_name eq 'Expose') {
    $X->PolyRectangle ($window, $gc, [ 10,10,     # x,y top-left corner
                                       30,20 ]);  # width,height
    $X->PolyText8 ($window, $gc,
                   10, 55,    # X,Y of text baseline
                   [ 0,  # delta X
                     'Hello ... click mouse button to exit.' ]);

  } elsif ($event_name eq 'ButtonPress') {
    exit 0;
  }
};

$X->MapWindow ($window);
for (;;) {
  $X->handle_input;
}

Phix

Translation of: TXR

See Window_creation#Phix

PicoLisp

The following script works in the 32-bit version, using inlined C code

#!/usr/bin/picolisp /usr/lib/picolisp/lib.l

(load "@lib/misc.l" "@lib/gcc.l")

(gcc "x11" '("-lX11") 'simpleWin)

#include <X11/Xlib.h>

any simpleWin(any ex) {
   any x = cdr(ex);
   int dx, dy;
   Display *disp;
   int scrn;
   Window win;
   XEvent ev;

   x = cdr(ex),  dx = (int)evCnt(ex,x);
   x = cdr(x),  dy = (int)evCnt(ex,x);
   x = evSym(cdr(x));
   if (disp = XOpenDisplay(NULL)) {
      char msg[bufSize(x)];

      bufString(x, msg);
      scrn = DefaultScreen(disp);
      win = XCreateSimpleWindow(disp, RootWindow(disp,scrn), 0, 0, dx, dy,
                           1, BlackPixel(disp,scrn), WhitePixel(disp,scrn) );
      XSelectInput(disp, win, ExposureMask | KeyPressMask | ButtonPressMask);
      XMapWindow(disp, win);
      for (;;) {
         XNextEvent(disp, &ev);
         switch (ev.type) {
         case Expose:
            XDrawRectangle(disp, win, DefaultGC(disp, scrn), 10, 10, dx-20, dy-20);
            XDrawString(disp, win, DefaultGC(disp, scrn), 30, 40, msg, strlen(msg));
            break;
         case KeyPress:
         case ButtonPress:
            XCloseDisplay(disp);
            return Nil;
         }
      }
   }
   return mkStr("Can't open Display");
}
/**/

(simpleWin 300 200 "Hello World")
(bye)

Python

Xlib

This example needs review by someone who knows about: X11
Note (stolen from CLX example): This example was written in near-total ignorance of X11 by consulting the python-xlib's examples (included in its distribution) to find equivalents for the parts of the C example.

If you know X11, please review this example and, as necessary, improve it or describe what should be done for someone who knows the language.

Translation of: C
Library: python-xlib

Download Python X library from http://sourceforge.net/projects/python-xlib/ . python-xlib is a pure python library therefore the example should work anywhere where python does and where there is an X server. Run:

  • python xlib_hello_world.py
from Xlib import X, display

class Window:
    def __init__(self, display, msg):
        self.display = display
        self.msg = msg
        
        self.screen = self.display.screen()
        self.window = self.screen.root.create_window(
            10, 10, 100, 100, 1,
            self.screen.root_depth,
            background_pixel=self.screen.white_pixel,
            event_mask=X.ExposureMask | X.KeyPressMask,
            )
        self.gc = self.window.create_gc(
            foreground = self.screen.black_pixel,
            background = self.screen.white_pixel,
            )

        self.window.map()

    def loop(self):
        while True:
            e = self.display.next_event()
                
            if e.type == X.Expose:
                self.window.fill_rectangle(self.gc, 20, 20, 10, 10)
                self.window.draw_text(self.gc, 10, 50, self.msg)
            elif e.type == X.KeyPress:
                raise SystemExit

                
if __name__ == "__main__":
    Window(display.Display(), "Hello, World!").loop()

XCB

Library: python-xcb
import xcb
from xcb.xproto import *
import xcb.render

def main():
  conn = xcb.connect()
  conn.render = conn(xcb.render.key)

  setup = conn.get_setup()
  root = setup.roots[0].root
  depth = setup.roots[0].root_depth
  visual = setup.roots[0].root_visual
  white = setup.roots[0].white_pixel

  window = conn.generate_id()
  conn.core.CreateWindow(depth, window, root,
                         0, 0, 640, 480, 0,
                         WindowClass.InputOutput,
                         visual,
                         CW.BackPixel | CW.EventMask,
                         [ white, EventMask.Exposure |
                                  EventMask.KeyPress ])

  conn.core.MapWindow(window)
  conn.flush()

  while True:
    event = conn.wait_for_event()

    if isinstance(event, ExposeEvent):
      color = (0, 0, 65535, 65535)
      rectangle = (20, 20, 40, 40)
      # TODO, fixme:
      # I haven't been able to find what I should put for the parameter "op"
   #  conn.render.FillRectangles(op, window, color, 1, rectangle)
      conn.flush()

    elif isinstance(event, KeyPressEvent):
      break

  conn.disconnect()

main()

Racket

Using Racket's GUI which is implemented using gtk. It's not low level, but OTOH it works on Windows and OS X too.

#lang racket/gui

(define frame (new frame%
                   [label "Example"]
                   [width 300]
                   [height 300]))
(new canvas% [parent frame]
             [paint-callback
              (lambda (canvas dc)
                (send dc set-scale 3 3)
                (send dc set-text-foreground "blue")
                (send dc draw-text "Don't Panic!" 0 0))])
(send frame show #t)

Raku

(formerly Perl 6)

Translation of: C

There is not yet a X11 library in Raku but we can write the minimal C mappings for this task.

use NativeCall;

class Display is repr('CStruct') {
    has int32 $!screen;
    has int32 $!window;
 }
class GC      is repr('CStruct') {
    has int32 $!context;
}
class XEvent  is repr('CStruct') {
    has int32 $.type;
    method init { $!type = 0 }
}

sub XOpenDisplay(Str $name = ':0') returns Display is native('X11') { * }
sub XDefaultScreen(Display $) returns int32 is native('X11') { * }
sub XRootWindow(Display $, int32 $screen_number) returns int32 is native('X11') { * }
sub XBlackPixel(Display $, int32 $screen_number) returns int32 is native('X11') { * }
sub XWhitePixel(Display $, int32 $screen_number) returns int32 is native('X11') { * }
sub XCreateSimpleWindow(
    Display $, int32 $parent_window, int32 $x, int32 $y,
    int32 $width, int32 $height, int32 $border_width,
    int32 $border, int32 $background
) returns int32 is native('X11') { * }
sub XMapWindow(Display $, int32 $window) is native('X11') { * }
sub XSelectInput(Display $, int32 $window, int32 $mask) is native('X11') { * }
sub XFillRectangle(
    Display $, int32 $window, GC $, int32 $x, int32 $y, int32 $width, int32 $height
) is native('X11') { * }
sub XDrawString(
    Display $, int32 $window, GC $, int32 $x, int32 $y, Str $, int32 $str_length
) is native('X11') { * }
sub XDefaultGC(Display $, int32 $screen) returns GC is native('X11') { * }
sub XNextEvent(Display $, XEvent $e)              is native('X11') { * }
sub XCloseDisplay(Display $)                      is native('X11') { * }

my Display $display = XOpenDisplay()
    or die "Can not open display";

my int $screen = XDefaultScreen($display);
my int $window = XCreateSimpleWindow(
    $display,
    XRootWindow($display, $screen),
    10, 10, 100, 100, 1,
    XBlackPixel($display, $screen), XWhitePixel($display, $screen)
);
XSelectInput($display, $window, 1 +< 15 +| 1);
XMapWindow($display, $window);

my Str $msg = 'Hello, World!';
my XEvent $e .= new; $e.init;
loop {
    XNextEvent($display, $e);
    if $e.type == 12 {
	    XFillRectangle($display, $window, XDefaultGC($display, $screen), 20, 20, 10, 10);
	    XDrawString($display, $window, XDefaultGC($display, $screen), 10, 50, $msg, my int $ = $msg.chars);
    }
    elsif $e.type == 2 {
	    last;
    }
}
XCloseDisplay($display);

Scala

Library: Scala
import scala.swing.{ MainFrame, SimpleSwingApplication }
import scala.swing.Swing.pair2Dimension

object WindowExample extends SimpleSwingApplication {
  def top = new MainFrame {
    title = "Hello!"
    centerOnScreen
    preferredSize = ((200, 150))
  }
}

Standard ML

Works with PolyML

open XWindows ;
val dp =  XOpenDisplay "" ;
val w = XCreateSimpleWindow (RootWindow dp) origin (Area {x=0,y=0,w=400,h=300}) 3 0 0xffffff ;
XMapWindow w;
XFlush dp ;
XDrawString w (DefaultGC dp) (XPoint {x=10,y=50})  "Hello World!" ;
XFlush dp ;

Tcl

Tcl does not come with a low-level connection to the X protocol, as it has long been distributed with Tk which offers a much higher-level interface (and which is portable to other platforms too). This means that the interface has to be crafted directly. This can be done with either SWIG or critcl. This example shows how to do it the latter way:

Low level interface

Library: critcl
package provide xlib 1
package require critcl

critcl::clibraries -L/usr/X11/lib -lX11
critcl::ccode {
    #include <X11/Xlib.h>
    static Display *d;
    static GC gc;
}

# Display connection functions
critcl::cproc XOpenDisplay {Tcl_Interp* interp char* name} ok {
    d = XOpenDisplay(name[0] ? name : NULL);
    if (d == NULL) {
	Tcl_AppendResult(interp, "cannot open display", NULL);
	return TCL_ERROR;
    }
    gc = DefaultGC(d, DefaultScreen(d));
    return TCL_OK;
}
critcl::cproc XCloseDisplay {} void {
    XCloseDisplay(d);
}

# Basic window functions
critcl::cproc XCreateSimpleWindow {
    int x  int y  int width  int height  int events
} int {
    int s = DefaultScreen(d);
    Window w = XCreateSimpleWindow(d, RootWindow(d,s), x, y, width, height, 0,
	    BlackPixel(d,s), WhitePixel(d,s));
    XSelectInput(d, w, ExposureMask | events);
    return (int) w;
}
critcl::cproc XDestroyWindow {int w} void {
    XDestroyWindow(d, (Window) w);
}
critcl::cproc XMapWindow {int w} void {
    XMapWindow(d, (Window) w);
}
critcl::cproc XUnmapWindow {int w} void {
    XUnmapWindow(d, (Window) w);
}

# Event receiver
critcl::cproc XNextEvent {Tcl_Interp* interp} char* {
    XEvent e;
    XNextEvent(d, &e);
    switch (e.type) {
	case Expose:	return "type expose";
	case KeyPress:	return "type key";
	/* etc. This is a cheap hack version. */
	default:	return "type ?";
    }
}

# Painting functions
critcl::cproc XFillRectangle {int w int x int y int width int height} void {
    XFillRectangle(d, (Window)w, gc, x, y, width, height);
}
critcl::cproc XDrawString {int w int x int y Tcl_Obj* msg} void {
    int len;
    const char *str = Tcl_GetStringFromObj(msg, &len);
    XDrawString(d, (Window)w, gc, x, y, str, len);
}

Note that this only does enough for this demo. A full adaptation is too long for RosettaCode...

This could then be used like this:

package require xlib

XOpenDisplay {}
set w [XCreateSimpleWindow 10 10 100 100 1]
XMapWindow $w
while {[lindex [XNextEvent] 0] == "expose"} {
    XFillRectangle $w 20 20 10 10
    XDrawString $w 10 50 "Hello, World!"
}
XDestroyWindow $w
XCloseDisplay

Higher level interface

Just because there is a low level package does not mean that it is pleasant to use from Tcl code. Therefore this second package wraps it up inside a higher-level package that provides a more natural way of interacting.

Works with: Tcl version 8.6

or

Library: TclOO
package require TclOO
package provide x11 1

namespace eval ::x {
    namespace export {[a-z]*}
    namespace ensemble create
    variable mask
    array set mask {
	KeyPress	1
	KeyRelease	2
	ButtonPress	4
	ButtonRelease	8
    }

    proc display {script} {
	XOpenDisplay {}
	catch {uplevel 1 $script} msg opts
	XCloseDisplay
	return -options $opts $msg
    }
    proc eventloop {var handlers} {
	upvar 1 $var v
	while 1 {
	    set v [XNextEvent]
	    uplevel 1 [list switch [dict get $v type] $handlers]
	}
    }

    oo::class create window {
	variable w
        constructor {x y width height events} {
	    set m 0
	    variable ::x::mask
	    foreach e $events {catch {incr m $mask($e)}}
	    set w [XCreateSimpleWindow $x $y $width $height $m]
	}
	method map {} {
	    XMapWindow $w
	}
	method unmap {} {
	    XUnmapWindow $w
	}
	method fill {x y width height} {
	    XFillRectangle $w $x $y $width $height
	}
	method text {x y string} {
	    XDrawString $w $x $y $string
	}
	destructor {
	    XDestroyWindow $w
	}
    }
}

This script puts the pieces together to carry out the details of the task.

package require x11

# With a display connection open, create and map a window
x display {
    set w [x window new 10 10 100 100 KeyPress]
    $w map

    x eventloop ev {
	expose {
	    # Paint the window
	    $w fill 20 20 10 10
	    $w text 10 50 "Hello, World!"
	}
	key {
	    # Quit the event loop
	    break
	}
    }

    $w destroy
}

Improving this by adding more sophisticated event handling and more window methods is left as an exercise.

TXR

See Window_creation#TXR.

Wren

Translation of: C
Library: Xlib


As it's not currently possible for Wren-cli to access Xlib directly, we embed a Wren script in a C application to complete this task.

/* Window_creation_X11.wren */

var KeyPressMask = 1 << 0
var ExposureMask = 1 << 15
var KeyPress     = 2
var Expose       = 12

foreign class XGC {
    construct default(display, screenNumber) {}
}

foreign class XEvent {
    construct new() {}

    foreign eventType
}

foreign class XDisplay {
    construct openDisplay(displayName) {}

    foreign defaultScreen()

    foreign rootWindow(screenNumber)

    foreign blackPixel(screenNumber)

    foreign whitePixel(screenNumber)

    foreign selectInput(w, eventMask)

    foreign mapWindow(w)

    foreign closeDisplay()

    foreign nextEvent(eventReturn)

    foreign createSimpleWindow(parent, x, y, width, height, borderWidth, border, background)

    foreign fillRectangle(d, gc, x, y, width, height)

    foreign drawString(d, gc, x, y, string, length)
}

var xd = XDisplay.openDisplay("")
if (xd == 0) {
    System.print("Cannot open display.")
    return
}
var s = xd.defaultScreen()
var w = xd.createSimpleWindow(xd.rootWindow(s), 10, 10, 100, 100, 1, xd.blackPixel(s), xd.whitePixel(s))
xd.selectInput(w, ExposureMask | KeyPressMask)
xd.mapWindow(w)
var msg = "Hello, World!"
var e = XEvent.new()
while (true) {
    xd.nextEvent(e)
    var gc = XGC.default(xd, s)
    if (e.eventType == Expose) {
        xd.fillRectangle(w, gc, 20, 20, 10, 10)
        xd.drawString(w, gc, 10, 50, msg, msg.count)
    }
    if (e.eventType == KeyPress) break
}
xd.closeDisplay()


We now embed this Wren script in the following C program, compile and run it.

/* gcc Window_creation_X11.c -o Window_creation_X11 -lX11 -lwren -lm */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include "wren.h"

/* C <=> Wren interface functions */

void C_displayAllocate(WrenVM* vm) {
    Display** pdisplay = (Display**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(Display*));
    const char *displayName = wrenGetSlotString(vm, 1);
    if (displayName == "") {
        *pdisplay = XOpenDisplay(NULL);
    } else {
        *pdisplay = XOpenDisplay(displayName);
    }
}

void C_gcAllocate(WrenVM* vm) {
    GC *pgc = (GC *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(GC));
    Display* display = *(Display**)wrenGetSlotForeign(vm, 1);
    int s = (int)wrenGetSlotDouble(vm, 2);
    *pgc = DefaultGC(display, s);
}

void C_eventAllocate(WrenVM* vm) {
    wrenSetSlotNewForeign(vm, 0, 0, sizeof(XEvent));
}

void C_eventType(WrenVM* vm) {
    XEvent e = *(XEvent *)wrenGetSlotForeign(vm, 0);
    wrenSetSlotDouble(vm, 0, (double)e.type);
}

void C_defaultScreen(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    int screenNumber = DefaultScreen(display);
    wrenSetSlotDouble(vm, 0, (double)screenNumber);
}

void C_rootWindow(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    int screenNumber = (int)wrenGetSlotDouble(vm, 1);
    Window w = RootWindow(display, screenNumber);
    wrenSetSlotDouble(vm, 0, (double)w);
}

void C_blackPixel(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    int screenNumber = (int)wrenGetSlotDouble(vm, 1);
    unsigned long p = BlackPixel(display, screenNumber);
    wrenSetSlotDouble(vm, 0, (double)p);
}

void C_whitePixel(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    int screenNumber = (int)wrenGetSlotDouble(vm, 1);
    unsigned long p = WhitePixel(display, screenNumber);
    wrenSetSlotDouble(vm, 0, (double)p);
}

void C_selectInput(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    Window w = (Window)wrenGetSlotDouble(vm, 1);
    long eventMask = (long)wrenGetSlotDouble(vm, 2);
    XSelectInput(display, w, eventMask);
}

void C_mapWindow(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    Window w = (Window)wrenGetSlotDouble(vm, 1);
    XMapWindow(display, w);
}

void C_closeDisplay(WrenVM* vm) {
    Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
    XCloseDisplay(display);
}

void C_nextEvent(WrenVM* vm) {
   Display* display = *(Display**)wrenGetSlotForeign(vm, 0);
   XEvent* pe = (XEvent*)wrenGetSlotForeign(vm, 1);
   XNextEvent(display, pe);
}

void C_createSimpleWindow(WrenVM* vm) {
    Display *display         = *(Display**)wrenGetSlotForeign(vm, 0);
    Window parent            = (Window)wrenGetSlotDouble(vm, 1);
    int x                    = (int)wrenGetSlotDouble(vm, 2);
    int y                    = (int)wrenGetSlotDouble(vm, 3);
    unsigned int width       = (unsigned int)wrenGetSlotDouble(vm, 4);
    unsigned int height      = (unsigned int)wrenGetSlotDouble(vm, 5);
    unsigned int borderWidth = (unsigned int)wrenGetSlotDouble(vm, 6);
    unsigned long border     = (unsigned long)wrenGetSlotDouble(vm, 7);
    unsigned long background = (unsigned long)wrenGetSlotDouble(vm, 8);
    Window w = XCreateSimpleWindow(display, parent, x, y, width, height, borderWidth, border, background);
    wrenSetSlotDouble(vm, 0, (double)w);
}

void C_fillRectangle(WrenVM* vm) {
    Display *display    = *(Display**)wrenGetSlotForeign(vm, 0);
    Drawable d          = (Drawable)wrenGetSlotDouble(vm, 1);
    GC gc               = *(GC *)wrenGetSlotForeign(vm, 2);
    int x               = (int)wrenGetSlotDouble(vm, 3);
    int y               = (int)wrenGetSlotDouble(vm, 4);
    unsigned int width  = (unsigned int)wrenGetSlotDouble(vm, 5);
    unsigned int height = (unsigned int)wrenGetSlotDouble(vm, 6);
    XFillRectangle(display, d, gc, x, y, width, height);
}

void C_drawString(WrenVM* vm) {
    Display *display    = *(Display**)wrenGetSlotForeign(vm, 0);
    Drawable d          = (Drawable)wrenGetSlotDouble(vm, 1);
    GC gc               = *(GC *)wrenGetSlotForeign(vm, 2);
    int x               = (int)wrenGetSlotDouble(vm, 3);
    int y               = (int)wrenGetSlotDouble(vm, 4);
    const char *string  = wrenGetSlotString(vm, 5);
    int length          = (int)wrenGetSlotDouble(vm, 6);
    XDrawString(display, d, gc, x, y, string, length);
}

WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
    WrenForeignClassMethods methods;
    methods.finalize = NULL;
    if (strcmp(className, "XDisplay") == 0) {
        methods.allocate = C_displayAllocate;
    } else if (strcmp(className, "XGC") == 0) {
        methods.allocate = C_gcAllocate;
    } else if (strcmp(className, "XEvent") == 0) {
        methods.allocate = C_eventAllocate;
    } else {
        methods.allocate = NULL;
    }
    return methods;
}

WrenForeignMethodFn bindForeignMethod(
    WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature) {
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "XEvent") == 0) {
            if (!isStatic && strcmp(signature, "eventType") == 0)        return C_eventType;
        } else if (strcmp(className, "XDisplay") == 0) {
            if (!isStatic && strcmp(signature, "defaultScreen()") == 0)  return C_defaultScreen;
            if (!isStatic && strcmp(signature, "rootWindow(_)") == 0)    return C_rootWindow;
            if (!isStatic && strcmp(signature, "blackPixel(_)") == 0)    return C_blackPixel;
            if (!isStatic && strcmp(signature, "whitePixel(_)") == 0)    return C_whitePixel;
            if (!isStatic && strcmp(signature, "selectInput(_,_)") == 0) return C_selectInput;
            if (!isStatic && strcmp(signature, "mapWindow(_)") == 0)     return C_mapWindow;
            if (!isStatic && strcmp(signature, "closeDisplay()") == 0)   return C_closeDisplay;
            if (!isStatic && strcmp(signature, "nextEvent(_)") == 0)     return C_nextEvent;
            if (!isStatic && strcmp(signature, "createSimpleWindow(_,_,_,_,_,_,_,_)") == 0) return C_createSimpleWindow;
            if (!isStatic && strcmp(signature, "fillRectangle(_,_,_,_,_,_)") == 0) return C_fillRectangle;
            if (!isStatic && strcmp(signature, "drawString(_,_,_,_,_,_)") == 0) return C_drawString;
        }
    }
    return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
    printf("%s", text);
}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
    switch (errorType) {
        case WREN_ERROR_COMPILE:
            printf("[%s line %d] [Error] %s\n", module, line, msg);
            break;
        case WREN_ERROR_STACK_TRACE:
            printf("[%s line %d] in %s\n", module, line, msg);
            break;
        case WREN_ERROR_RUNTIME:
            printf("[Runtime Error] %s\n", msg);
            break;
    }
}

char *readFile(const char *fileName) {
    FILE *f = fopen(fileName, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *script = malloc(fsize + 1);
    fread(script, 1, fsize, f);
    fclose(f);
    script[fsize] = 0;
    return script;
}

int main(int argc, char **argv) {
    WrenConfiguration config;
    wrenInitConfiguration(&config);
    config.writeFn = &writeFn;
    config.errorFn = &errorFn;
    config.bindForeignClassFn = &bindForeignClass;
    config.bindForeignMethodFn = &bindForeignMethod;
    WrenVM* vm = wrenNewVM(&config);
    const char* module = "main";
    const char* fileName = "Window_creation_X11.wren";
    char *script = readFile(fileName);
    WrenInterpretResult result = wrenInterpret(vm, module, script);
    switch (result) {
        case WREN_RESULT_COMPILE_ERROR:
            printf("Compile Error!\n");
            break;
        case WREN_RESULT_RUNTIME_ERROR:
            printf("Runtime Error!\n");
            break;
        case WREN_RESULT_SUCCESS:
            break;
    }
    wrenFreeVM(vm);
    free(script);
    return 0;
}
Output:
Same as C example.