Jump to content

Window creation/X11: Difference between revisions

→‎{{header|Tcl}}: Rewrite to be clearer about how different levels of interface can exist
(→‎{{header|Tcl}}: Rewrite to be clearer about how different levels of interface can exist)
Line 196:
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 [http://www.swig.org/ SWIG] or [[critcl]]. This example shows how to do it the latter way:
 
===Low level interface package===
{{libheader|critcl}}
<lang tcl>package provide xlib 1
Line 204:
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);
Line 217 ⟶ 218:
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
Line 231 ⟶ 232:
return (int) w;
}
critcl::cproc XDestroyWindow {int w} void {
 
XDestroyWindow(d, (Window) w);
critcl::cproc XMapWindow {int w} void {
XMapWindow(d, (Window) w);
Line 239 ⟶ 242:
}
 
# Event receiver
critcl::cproc XNextEvent {Tcl_Interp* interp} char* {
XEvent e;
Line 250 ⟶ 254:
}
 
# 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;
Line 260 ⟶ 264:
}</lang>
Note that this only does enough for this demo. A full adaptation is too long for RosettaCode...
 
===High level interface package===
This could then be used like this:
Just because there is a low level package does not mean that it is pleasant to use from Tcl code. Therefore it is wrapped up inside a higher-level package that provides a more natural way of interacting.
<lang tcl>package require Tcl 8.5xlib
 
package provide x 11
XOpenDisplay {}
renameset ::w [XCreateSimpleWindow ::x::Window 10 10 100 100 1]
XMapWindow $w
while {[XNextEvent] == "expose"} {
XFillRectangle $w 20 20 10 10
XDrawString $w 10 50 "Hello, World!"
}
XDestroyWindow $w
XCloseDisplay</lang>
===HighHigher level interface package===
Just because there is a low level package does not mean that it is pleasant to use from Tcl code. Therefore itthis issecond wrappedpackage wraps it up inside a higher-level package that provides a more natural way of interacting.
<lang tcl>package require xlibTcl 8.6
package provide xx11 111
 
namespace eval ::x {
Line 277 ⟶ 294:
 
proc display {script} {
OpenDisplayXOpenDisplay {}
catch {uplevel 1 $script} msg opts
XCloseDisplay
CloseDisplay
return -options $opts $msg
}
Line 285 ⟶ 302:
upvar 1 $var v
while 1 {
set v [WaitForEventXNextEvent]
uplevel 1 [list switch $v $handlers]
}
}
proc window {x y width height events} {
set m 0
variable mask
foreach e $events {catch {incr m $mask($e)}}
Window $x $y $width $height $m
}
 
oo::class create window {
package require xlib
variable maskw
rename ::XOpenDisplay ::x::OpenDisplay
proc window constructor {x y width height events} {
rename ::XCloseDisplay ::x::CloseDisplay
set m 0
rename ::XCreateSimpleWindow ::x::Window
variable ::x::mask
rename ::XMapWindow ::x::map
foreach e $events {catch {incr m $mask($e)}}
rename ::XUnmapWindow ::x::unmap
set w [XCreateSimpleWindow $x $y $width $height $m]
rename ::XNextEvent ::x::WaitForEvent
}
rename ::XFillRectangle ::x::fillrect
method map {} {
rename ::XDrawString ::x::text</lang>
XMapWindow $w
===Demonstration script===
}
method unmap {} {
XUnmapWindow $w
}
Windowmethod $fill {x $y $width $height} $m{
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>lappendpackage auto_pathrequire lib .x11
package require x
 
# With a display connection open, create and map a window
x display {
set w [x window new 10 10 100 100 KeyPress]
x$w map $w
 
x eventloop e {
expose {
# Paint the window
x fillrect $w fill 20 20 10 10
x$w text $w 10 50 "Hello, World!"
}
key {
Line 327 ⟶ 351:
}
}
 
$w destroy
}</lang>
Improving this by adding more sophisticated event handling and more window methods is left as an exercise.
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.