{$MODE OBJFPC}
program xwin;

uses x,xlib, keysym, classes, sysutils;

type
  TDisplayWindow = class
  private
    display       : pDisplay;
    RootWindow    : TWindow;
    CurrentWindow : TWindow;
  public
    constructor create(display_link : PChar);
    destructor destroy; override;
    procedure execute;
  end;

constructor TDisplayWindow.create(display_link : PChar);
begin
  self.display := XOpenDisplay(display_link); // lets get the x-server connection

  if (display = nil) then
    raise Exception.CreateFmt('Unable to open a display at %s.', [display_link]);

  self.RootWindow    := XDefaultRootWindow(self.display); // Get the root window (sometimes the desktop...)
  //                                   Display pointer     Window pointer    x  y   w    h
  self.CurrentWindow := XCreateSimpleWindow(self.display,  self.RootWindow,  0, 0, 100, 200,
                                       1,  // Border width
                                       10, // Border
                                       XWhitePixel(self.display, 0)); // Background color <- on a regular xlib app, you should use XWhitePixel and XBlackPixel only once, so save the value in a variable
  // set events 
  XSelectInput(self.display, self.CurrentWindow,
               KeyPressMask); // what event to read...

  // set the window in x11
  XMapWindow(self.display, self.CurrentWindow);
end;

destructor TDisplayWindow.destroy;
begin
  XDestroyWindow(self.display, self.CurrentWindow);
  XCloseDisplay(self.display);
  inherited;
end;


procedure TDisplayWindow.execute;
var
  Events_Status : TXEvent; // event
  Key           : Tkeysym; // key
  ToBreak       : Boolean;
begin
  ToBreak := false;
  while (not ToBreak) do
   begin
     XNextEvent(self.display, @Events_Status);
     case Events_Status._type of
       KeyPress : begin
                   Key := XKeycodeToKeysym(self.display, Events_Status.xkey.keycode, 0); // convert regular keybard to Xkeyscan code
                   case Key of 
                     XK_Escape : ToBreak := true;
                   else writeln('The user is pressing on ', XKeysymToString (Key)); // display what is the key name 
                   end;
                  end;
       else XFlush(self.display); // paint the window on screen
     end;
   end;
end;

var
  Window : TDisplayWindow;

begin
  Window := TDisplayWindow.Create(':0');
  try
    Window.Execute;
  finally
    Window.Free;
  end;
end.

