Window creation/X11: Difference between revisions
(Adding Groovy) |
m (added whitespace before the TOC (table of contents), added a ;Task: (bold) header, added highlighting.) |
||
Line 1: | Line 1: | ||
{{task|GUI}}{{requires|Graphics}} |
{{task|GUI}}{{requires|Graphics}} |
||
⚫ | |||
;Task: |
|||
⚫ | |||
Implementations of this task should ''avoid using a toolkit'' as much as possible. |
|||
<br><br> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
Revision as of 17:23, 22 June 2016
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.
ALGOL 68
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. <lang algol68>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)</lang>
C
Xlib
Compile with:
- gcc hello-x.c -L/usr/X11R6/lib -lX11 -o hello-x
<lang c>#include <X11/Xlib.h>
- include <stdio.h>
- include <stdlib.h>
- include <string.h>
int main(void) {
Display *d; Window w; XEvent e; 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;
}</lang>
XCB
Compile with:
- gcc -o helloxcb helloxcb.c -lxcb
<lang c>#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;
}</lang>
COBOL
Tested with GnuCOBOL, and only on 64bit architecture, GNU/Linux. Nods to the C XLib version.
<lang cobol> 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.</lang>
Common Lisp
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.
<lang lisp>;;; Single-file/interactive setup; large applications should define an ASDF system instead (cl:require :asdf) (asdf:operate 'asdf:load-op :clx) (cl:defpackage #:rc-xlib-window
(:use #:cl #:xlib))
(cl:in-package #:rc-xlib-window)
(let ((display (open-default-display)))
(unwind-protect (let* ((window (create-window :parent (screen-root (display-default-screen display)) :x 10 :y 10 :width 100 :height 100 :event-mask '(:exposure :key-press))) (gc (create-gcontext :drawable window))) (map-window window) (event-case (display :discard-p t) (exposure () (draw-rectangle window gc 20 20 10 10 t) (draw-glyphs window gc 10 40 "Hello, World!") nil #| continue receiving events |#) (key-press () t #| non-nil result signals event-case to exit |#)))) (close-display display))</lang>
Go
<lang go>package main
import (
"code.google.com/p/x-go-binding/xgb" "fmt"
)
func main() {
c, err := xgb.Dial("") if err != nil { fmt.Println(err) return } defer c.Close()
strBytes := []byte("Hello XGB!") rectangles := []xgb.RectangleTemplate:40, 40, 20, 20
// get the first screen s := c.DefaultScreen()
// root window win := s.Root
// create black (foreground) graphic context fg := c.NewId() mask := uint32(xgb.GCForeground | xgb.GCGraphicsExposures) values := []uint32{s.BlackPixel, 0} c.CreateGC(fg, win, mask, values)
// create white (background) graphic context bg := c.NewId() mask = uint32(xgb.GCBackground | xgb.GCGraphicsExposures) values[0] = s.WhitePixel // (values[1] still 0) c.CreateGC(bg, win, mask, values)
// create the window win = c.NewId() mask = xgb.CWBackPixel | xgb.CWEventMask // values[0] still s.WhitePixel values[1] = xgb.EventMaskExposure | xgb.EventMaskKeyPress c.CreateWindow(0, win, s.Root, 0, 0, 150, 150, 10, xgb.WindowClassInputOutput, s.RootVisual, mask, values) c.MapWindow(win)
for { event, err := c.WaitForEvent() if err != nil { fmt.Println(err) return } switch event.(type) { case xgb.ExposeEvent: c.PolyRectangle(win, fg, rectangles) c.ImageText8(win, bg, 20, 20, strBytes) case xgb.KeyPressEvent: return } }
}</lang> Screen capture:
Groovy
Run:
groovy WindowCreation.groovy
<lang 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) } }
}</lang>
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:
<lang guiss>Start,Programs,Applications,Editors,Leafpad,Textbox, Type:[openbox]Hello World[pling][closebox]</lang>
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. <lang Icon>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</lang>
graphics.icn provides graphics
Additionally, the WOpen procedure and Window.App methods are available.
Haskell
Using
from HackageDB
<lang haskell>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
</lang>
Java
compile
javac WindowExample.java
run
java WindowExample
<lang java>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); }
}</lang>The previous example works but doesn't write any text or draw any box; the following does both.<lang java>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); }
}</lang>
Mathematica
Note that GUIKit is a high-level wrapper for Swing.
<lang>
Needs["GUIKit`"] ref = GUIRun[Widget["Panel", { Widget[ "ImageLabel", {"data" -> Script[ExportString[Graphics[Rectangle[{0, 0}, {1, 1}]], "GIF"]]}], Widget["Label", { "text" -> "Hello World!"}]} ]]
</lang>
OCaml
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"
<lang ocaml>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;
- </lang>
Pascal
from wiki.freepascal.org/X11#Examples. Compiled with Freepascal 2.6.4-32 <lang pascal>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. </lang>
Perl
X11::Protocol
<lang perl>#!/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;
}</lang>
Perl 6
There is not yet a X11 library in Perl 6 but we can write the minimal C mappings for this task. Notice that the mapping for XEvent requires a manual set up which depends on the number of bits of your machine. This is due to a current bug in NativeCall on MoarVM.
<lang perl6>use NativeCall;
class Display is repr('CStruct') {} class GC is repr('CStruct') {} class XEvent is repr('CStruct') {
has int32 $.type; # for 32 bits machine #has int $.type; # for 64 bits machine method init { $!type = 0 }
}
sub XOpenDisplay(Str $name = ':0') returns Display is native('libX11') { * } sub XDefaultScreen(Display $) returns int is native('libX11') { * } sub XRootWindow(Display $, int $screen_number) returns int is native('libX11') { * } sub XBlackPixel(Display $, int $screen_number) returns int is native('libX11') { * } sub XWhitePixel(Display $, int $screen_number) returns int is native('libX11') { * } sub XCreateSimpleWindow(
Display $, int $parent_window, int $x, int $y, int $width, int $height, int $border_width, int $border, int $background
) returns int is native('libX11') { * } sub XMapWindow(Display $, int $window) is native('libX11') { * } sub XSelectInput(Display $, int $window, int $mask) is native('libX11') { * } sub XFillRectangle(
Display $, int $window, GC $, int $x, int $y, int $width, int $height
) is native('libX11') { * } sub XDrawString(
Display $, int $window, GC $, int $x, int $y, Str $, int $str_length
) is native('libX11') { * } sub XDefaultGC(Display $, int $screen) returns GC is native('libX11') { * } sub XNextEvent(Display $, XEvent $e) is native('libX11') { * } sub XCloseDisplay(Display $) is native('libX11') { * }
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);</lang>
PicoLisp
The following script works in the 32-bit version, using inlined C code <lang PicoLisp>#!/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)</lang>
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
<lang python>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()</lang>
XCB
<lang python>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()</lang>
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>#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)</lang>
Scala
<lang 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)) }
}</lang>
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
<lang tcl>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);
}</lang> Note that this only does enough for this demo. A full adaptation is too long for RosettaCode...
This could then be used like this: <lang tcl>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</lang>
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.
or
<lang tcl>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 }
}
}</lang> This script puts the pieces together to carry out the details of the task. <lang tcl>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
}</lang> Improving this by adding more sophisticated event handling and more window methods is left as an exercise. omit from|ZX Spectrum Basic|No X11 server access.}}
- Programming Tasks
- GUI
- ALGOL 68
- AutoHotkey/Omit
- C
- Xlib
- XCB
- COBOL
- Common Lisp
- Common Lisp examples needing attention
- Examples needing attention
- Field knowledge needed/X11
- Field knowledge needed/X11/Common Lisp
- CLX
- Go
- Groovy
- GUISS
- Icon
- Unicon
- Icon Programming Library
- Haskell
- X11
- Java
- Mathematica
- OCaml
- OCaml-Xlib
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- PureBasic/Omit
- Pascal
- XLib, x ,ctypes
- Perl
- Perl 6
- PicoLisp
- Python
- Python examples needing attention
- Field knowledge needed/X11/Python
- Python-xlib
- Python-xcb
- Racket
- Scala
- Tcl
- Critcl
- TclOO
- ACL2/Omit
- Batch File/Omit
- AWK/Omit
- Erlang/Omit
- Locomotive Basic/Omit
- Logtalk/Omit
- Lotus 123 Macro Scripting/Omit
- M4/Omit
- Maxima/Omit
- PARI/GP/Omit
- PostScript/Omit
- PowerBASIC/Omit
- SNOBOL4/Omit
- TPP/Omit
- Unlambda/Omit
- Retro/Omit