Updated 2018-01-29 06:13:16 by DDG

Widget wrapper on Linux Systems for the surf webbrowser edit

An easy wrapper for the lightweight surf webbrowser on Linux systems to embed an htmlviewer into Tcl/Tk applications . Requires surf and xprop tools. Works on X but not on Wayland as Wayland does not support the Xembed protocol.


Source Code:
#  Created By    : Dr. Detlef Groth
#  Created       : Mon Jan 29 05:11:44 2018
#  Last Modified : <180129.0605>
#  Description         : A web browser widget for Tcl/Tk using the 
#                  minimimal web browser surf see:
#                  https://surf.suckless.org/ 
#  Notes         : surve can be driven by setting it's x-properties for instance 
#                  using the commandline tool xprop
#                  as surf supports the Xembed protocol it should run without TkXext, but it did not show up without
#  Requirements  : surf and xprop 
#                  on fedora: dnf install surf xprop
#  History       : 0.1 initial release 2018-01-29
#  Copyright (c) 2018 Dr. Detlef Groth.
#  License BSD

package require Tk
package require TkXext
package require snit
package provide SnitXSurf 0.1

snit::widget SnitXSurf {
    option -home http://www.duckduckgo.com
    option -search http://duckduckgo.com/?q=
    variable surf
    constructor {args} {
        $self configurelist $args
        # install check
        foreach tool [list surf xprop] {
            set ok [auto_execok $tool]
            if {$ok eq ""} {
                return -code error "please install $tool for usage of SnitXSurf"
        frame $win.f -width 200 -height 200 -container 1
        set sin [open "|surf -e [expr [winfo id $win.f]] dummy  &" r]
        #exec surf -e [expr [winfo id $win.f]] dummy  &
        # in principle we could get the xiud directly
        # but this does not work (yet)
        # -e embeds but surf is invisible still so we need TkXext
        fconfigure $sin -blocking false -buffering none
        fileevent $sin readable [list EmbedSurf $sin]
        set surf [TkXext.find.window *dummy*];
        while {$surf eq ""} {
            after 500
            set surf [TkXext.find.window *dummy*];
            if {[incr x] > 20} {
        if {$surf eq ""} {
            destroy $win.f
            return -code error "unable to find the Surf window"
        # as -e did not work for surf on Tk
        TkXext.reparent.window $surf [winfo id $win.f]
        bind $win.f <Configure> [list TkXext.resize.window $surf %w %h]
        pack $win.f -fill both -expand 1
        exec  xprop -id [expr 0x$surf]  -f _SURF_GO 8s -set _SURF_GO $options(-home) &
        bind $win.f <Destroy> [list [mymethod KillSurf] %W]
    method browse {url} {
        exec  xprop -id [expr 0x$surf]  -f _SURF_GO 8s -set _SURF_GO $url &
    method search {keyword} {
        exec  xprop -id [expr 0x$surf]  -f _SURF_GO 8s -set _SURF_GO $options(-search)$keyword &
    method KillSurf {w} {
        TkXext.delete.or.kill $surf
    method EmbedSurf {chan} {
        # not used yet
        # you might use stdout with your own surf version for
        # communicating via stdout
        if {[gets $chan line] < 0} {
            if {[eof $chan]} {
                close $chan
            # Could not read a complete line this time; Tcl's
            # internal buffering will hold the partial line for us
            # until some more data is available over the socket.
        } else {
            puts stdout $line

if {$argv0 eq [info script]} {
    if {[llength $argv] <= 1 } {
        SnitXSurf .surf -home http://www.duckduckgo.com
        pack .surf -side top -fill both -expand true
        if {[llength $argv] == 1} {
            .surf browse [lindex $argv 0]

Discussion  edit