**A Snit Widget which can embed almost any application on X-Window window managers** Yes, I use a tiling window manager - I3, gnu screen for managing terminals. But still I feel do need to better group related windows together. That's what SnitXWindow for. You can embed an arrange all related windows into one Tk window. You can put them in tabs, or paned windows. You can move or activate your Terminals, editor, your pdf viewer your browser window, your spreedsheet etc all related to your project in one step. This extension works only on X-Windows, requires [TkXext] and [Snit]. Hopefully that X will be alive for some time despite of Wayland ... ====== # Created By : Dr. Detlef Groth # Created : Mon Jan 29 05:11:44 2018 # Last Modified : <180216.0722> # # Description : A snit widget for embedding other X-applications # # # Notes : xprop require to get window properties # using the commandline tool xprop # Requirements : xprop , should be installed on X-Window systems # # History : 0.1 initial release 2018-01-29 # : 0.2 embedding zathura, mupdf in the empty field # window title using xprop # : 0.3 avoid reparenting already embeded window # ############################################################################## # # Copyright (c) 2018 Dr. Detlef Groth. # # License BSD snit::widget SnitXWindow { option -cmd xterm option -embedoption "" option -searchtitle "" option -cmdargs "" variable app "" variable pid "" variable WinTitle "" variable DynTitle "" constructor {args} { $self configurelist $args pack [frame $win.status] -side top -fill x -expand false pack [label $win.status.lb -textvariable [myvar DynTitle]] -side left -fill x -expand false # install check set ok [auto_execok $options(-cmd)] if {$options(-cmd) != ""} { if {$ok eq ""} { return -code error "please install $options(-cmd)" } $self LoadApp } else { $self EmbedByTitleFrame } bind $win [mymethod EnterWin] bind $win [mymethod LoadApp] bind $win [mymethod ReopenWithNewFile] } method EmbedByTitleFrame {} { if {![winfo exists $win.top]} { frame $win.top pack [label $win.top.lbl -text "Window Title:"] -padx 3 -side left pack [entry $win.top.ent -textvariable [myvar WinTitle]] -side left -padx 3 pack [button $win.top.btn -text "Embed Window" -command [mymethod EmbedTitle]] -side left -padx 3 pack $win.top -fill x -expand false -side top } } method ReadPipe {chan} { set d [read $chan] foreach line [split $d \n] { if {[regexp {^WM_NAME.STRING. = "(.+)"} $line m title] } { set DynTitle $title } } if {[eof $chan]} { fileevent $chan readable {} close $chan } } method getWinState {} { set state Normal set res [exec xprop -id 0x$app] foreach line [split $res "\n"] { if {[regexp {window state: ([^ ]+)} $line -> state]} { break } } return $state } method getWinProperties {} { set xpin [open "|xprop -id 0x$app -spy" r] fconfigure $xpin -blocking 0 -buffering line fileevent $xpin readable [mymethod ReadPipe $xpin] } method EmbedTitle {} { if {[regexp {surf +(.+)} $WinTitle -> url]} { SnitXSurf $win.f -home $url } elseif {[regexp {zathura} $WinTitle] || [regexp {mupdf} $WinTitle] } { set types { {{Pdf Files} {.pdf} } {{Ps Files} {.ps} } {{Comic Files} {.cbz} } {{All Files} { *} } } if {[regexp {mupdf} $WinTitle] } { set types { {{Pdf Files} {.pdf} } {{Ebook Files} {.epub} } {{Comic Files} {.cbz} } {{All Files} { *} } } } set filename [tk_getOpenFile -filetypes $types] if {$filename != ""} { if {[regexp {zathura} $WinTitle]} { SnitXWindow $win.f -cmd zathura -cmdargs $filename -searchtitle $filename } else { SnitXMupdf $win.f -infile $filename -standalone false } } } else { set app [TkXext.find.window $WinTitle]; if {![winfo exists $win.f]} { frame $win.f -width 200 -height 200 -container 1 } while {$app eq ""} { after 200 set app [TkXext.find.window $WinTitle]; if {[incr x] > 10} { break } } if {$app eq "" || $app == 0} { tk_messageBox -title "Info!" -icon info -message "Unable to find window '$WinTitle'!\nHint: Try a * at the End!" -type ok return } TkXext.reparent.window $app [winfo id $win.f] bind $win.f [list TkXext.resize.window $app %w %h] bind $win.f [list TkXext.delete.or.kill $app] bind $win [list pack $win.top] $self getWinProperties } pack $win.f -fill both -expand 1 -side top pack forget $win.top } method ReopenWithNewFile {} { if {$options(-cmd) eq "mupdf"} { set types { {{Pdf Files} {.pdf} } {{Epub Files} {.epub} } {{All Files} * } } set filename [tk_getOpenFile -filetypes $types] if {$filename != ""} { puts $filename set options(-cmdargs) [file nativename $filename] set options(-searchtitle) "[file tail [file nativename $filename]]*" if {[winfo exists $win.f]} { destroy $win.f } $self LoadApp } } } method LoadApp {} { if {![winfo exists $win.f]} { frame $win.f -width 200 -height 200 -container 1 } if {$options(-embedoption) eq ""} { set pid [exec $options(-cmd) {*}$options(-cmdargs) &] } set app "" while {$app eq ""} { after 200 set app [TkXext.find.window $options(-searchtitle)]; set state [$self getWinState] if { $state eq "Withdrawn" } { # window was already catched # wait for the fresh one!! # don't steal set app "" } if {[incr x] > 100} { break } } if {$app eq ""} { destroy $win.f return -code error "unable to find the $options(-cmd) window" } TkXext.reparent.window $app [winfo id $win.f] bind $win.f [list TkXext.resize.window $app %w %h] pack $win.f -fill both -expand 1 if {$options(-cmd) eq "urxvt"} { pack forget $win.status } else { $self getWinProperties } } method EnterWin {} { catch {focus -force $win} } destructor { try { exec kill $pid } finally { try { # TkXext.delete.or.kill $app # did not work } } destroy $win } } ====== <>Gui | Snit Widgets | X-Windows