2021-12-19 03:59:42 +00:00
#!/usr/bin/env python3
"""
This uses the currently supported WebKit GTK , which is more up to date but also fatter .
WebKit is a huge mess and leaks all over the place . I ' m not even sure about anything that ' s going on . Resources are taken up but only loosely released . You can start with as low as a 50 MB memory load , but you will never go back to that . There ' s no apparent way to run JavaScript garbage collection, and I doubt it would help. -- Par of the course for JavaScript supporting browsers.
Good : This is a little less fat than Chrome , probably . . maybe . . at least at first
Bad : It still sucks
Prerequisites ( Debian and cousins ) :
sudo apt install python3 - gi python3 - gi - cairo gir1 .2 - gtk - 3.0 gir1 .2 - webkit2 - 4.0
2021-12-20 05:41:56 +00:00
Below " # Script start " you can find a setting for software mode , which you should comment out if you use a modern PC . I don ' t use the software rendering that comes included with WebKit, as it ' s unstable in my experience .
2021-12-19 03:59:42 +00:00
"""
import sys
oldexcepthook = sys . excepthook
def newexcepthook ( type , value , traceback ) :
oldexcepthook ( type , value , traceback )
#input("Press ENTER to quit.")
sys . excepthook = newexcepthook
import os
p = os . path . join
pUp = os . path . dirname
s = False
if getattr ( sys , ' frozen ' , False ) and hasattr ( sys , ' _MEIPASS ' ) :
s = os . path . realpath ( sys . executable )
else :
s = os . path . realpath ( __file__ )
sp = pUp ( s )
# Script start
import gi
gi . require_version ( " Gtk " , " 3.0 " )
gi . require_version ( " WebKit2 " , " 4.0 " )
from gi . repository import Gtk , WebKit2
defaultProtocol = " https "
browserWindows = [ ]
class emptyClass ( ) : pass ;
measure = emptyClass ( )
measure . toolbar = 22
def parseUrl ( url ) :
if url . startswith ( " data: " ) : return " data " , [ ] , " " , " "
if url . startswith ( " blob: " ) : return " blob " , [ ] , " " , " "
urlSplit = url . split ( " : " , 1 )
protocol = urlSplit [ 0 ]
urlSplit = urlSplit [ 1 ] . lstrip ( " / " ) . split ( " / " , 1 )
if len ( urlSplit ) < 2 : urlSplit . append ( " " )
domain = urlSplit [ 0 ] . split ( " . " )
urlSplit = urlSplit [ 1 ] . split ( " ? " , 1 )
if len ( urlSplit ) < 2 : urlSplit . append ( " " )
path = urlSplit [ 0 ]
arguments = urlSplit [ 1 ]
return protocol , domain , path , arguments
birdyWebContext = WebKit2 . WebContext ( )
birdyWebContext . set_cache_model ( WebKit2 . CacheModel . DOCUMENT_VIEWER ) # Does this even do anything at all?
birdyWebContext . set_spell_checking_enabled ( False )
birdyWebContext . set_use_system_appearance_for_scrollbars ( True )
birdyWebSettings = WebKit2 . Settings . new ( )
#birdyWebSettings.set_auto_load_images(False)
birdyWebSettings . set_enable_developer_extras ( False )
birdyWebSettings . set_enable_page_cache ( False )
2022-06-08 19:12:02 +00:00
birdyWebSettings . set_hardware_acceleration_policy ( WebKit2 . HardwareAccelerationPolicy . NEVER )
2021-12-19 03:59:42 +00:00
defaultUserAgent = birdyWebSettings . get_user_agent ( )
2022-06-08 19:14:37 +00:00
singleProcessMode = False
remakeViewOnNavigation = False # Always entirely remake view on navigation, could break some websites - use for super low memory situations
2021-12-19 03:59:42 +00:00
def birdyWebViewConstructor ( webView ) :
2022-06-08 19:14:37 +00:00
if webView and singleProcessMode :
2021-12-19 03:59:42 +00:00
return WebKit2 . WebView . new_with_related_view ( webView )
self = WebKit2 . WebView . new_with_context ( birdyWebContext )
self . set_settings ( birdyWebSettings )
return self
class birdyBrowserWindow ( Gtk . Window ) :
def __init__ ( self , webView , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
2021-12-20 05:46:31 +00:00
self . cTitle = " webkit-inabox-gtk "
self . set_title ( self . cTitle )
2021-12-19 03:59:42 +00:00
self . cWidth = 640
self . cHeight = 480
self . resize ( self . cWidth , self . cHeight )
self . connect ( " destroy " , self . cCloseEvent )
self . connect ( " configure-event " , self . cConfigureEvent )
self . cCreateElements ( webView )
def cCreateElements ( self , webView ) :
self . cMainBoxWrapper = Gtk . ScrolledWindow ( )
self . add ( self . cMainBoxWrapper )
self . cMainBox = Gtk . Fixed ( )
self . cMainBoxWrapper . add ( self . cMainBox )
self . cMenuBar = Gtk . MenuBar ( )
self . cMainBox . add ( self . cMenuBar )
# Menu - File
self . cFileMenuButton = Gtk . MenuItem . new_with_label ( " File " )
self . cFileMenu = Gtk . Menu ( )
self . cFileMenuNewWindow = Gtk . MenuItem . new_with_label ( " New window " )
self . cFileMenuNewWindow . connect ( " activate " , self . cOpenWindow )
self . cFileMenu . add ( self . cFileMenuNewWindow )
self . cFileMenuButton . set_submenu ( self . cFileMenu )
self . cMenuBar . add ( self . cFileMenuButton )
2021-12-20 05:46:31 +00:00
# Menu - Loading indication
self . cMenuLoadingIndication = Gtk . MenuItem . new_with_label ( " Loading... " )
self . cMenuBar . add ( self . cMenuLoadingIndication )
2021-12-19 03:59:42 +00:00
homepage = " about:blank "
2022-06-08 19:14:37 +00:00
self . cLastUrl = " about:blank "
2021-12-19 03:59:42 +00:00
self . cUrlEntry = Gtk . Entry ( )
self . cUrlEntry . set_text ( homepage )
#self.cUrlEntry.props.enable_emoji_completion = True # lol
self . cUrlEntry . connect ( " activate " , self . cUrlEntryNavigate )
self . cMainBox . add ( self . cUrlEntry )
2022-06-08 19:14:37 +00:00
self . cCreateWebView ( webView )
2021-12-19 03:59:42 +00:00
self . cWebView . load_uri ( homepage )
self . cResizeElements ( )
self . set_focus ( self . cUrlEntry )
self . cUrlEntry . select_region ( 0 , 2 )
self . show_all ( )
2021-12-20 05:46:31 +00:00
self . cMenuLoadingIndication . hide ( )
2021-12-19 03:59:42 +00:00
2022-06-08 19:14:37 +00:00
def cCreateWebView ( self , webView ) :
self . cWebView = birdyWebViewConstructor ( webView )
self . cWebView . connect ( " load-changed " , self . cWebViewLoadChanged )
self . cWebView . connect ( " notify::uri " , self . cUrlChanged )
self . cWebView . connect ( " notify::title " , self . cTitleChanged )
self . cMainBox . add ( self . cWebView )
2021-12-19 03:59:42 +00:00
def cResizeElements ( self ) :
# cMenuBar
self . cMainBox . move ( self . cMenuBar , 0 , 0 )
self . cMenuBar . set_size_request ( self . cWidth , measure . toolbar )
# cUrlEntry
self . cMainBox . move ( self . cUrlEntry , 0 , measure . toolbar )
self . cUrlEntry . set_size_request ( self . cWidth , measure . toolbar )
# cWebView
self . cMainBox . move ( self . cWebView , 0 , measure . toolbar * 2 )
self . cWebView . set_size_request ( self . cWidth , self . cHeight - ( measure . toolbar * 2 ) )
def cConfigureEvent ( self , widget , event ) :
if event . width == self . cWidth and event . height == self . cHeight : return
self . cWidth = event . width
self . cHeight = event . height
self . cResizeElements ( )
def cCloseEvent ( self , * args , * * kwargs ) :
browserWindows . remove ( self )
self . cWebView . destroy ( )
self . destroy ( )
if len ( browserWindows ) > 0 : return
Gtk . main_quit ( )
2021-12-20 05:46:31 +00:00
def cUrlChanged ( self , widget , prop ) :
2021-12-19 03:59:42 +00:00
url = widget . get_uri ( )
2022-06-08 19:14:37 +00:00
if url != self . cLastUrl and remakeViewOnNavigation and not singleProcessMode :
self . cWebView . destroy ( )
self . cCreateWebView ( False )
self . cResizeElements ( )
self . show_all ( )
self . cWebView . load_uri ( url )
self . cLastUrl = url
2021-12-20 05:46:31 +00:00
if url == " about:blank " : return
2022-06-09 14:30:37 +00:00
if url == " " : return
2021-12-19 03:59:42 +00:00
if self . cUrlEntry . get_text ( ) != url : self . cUrlEntry . set_text ( url )
2021-12-20 05:46:31 +00:00
def cTitleChanged ( self , widget , prop ) :
2022-06-09 14:30:37 +00:00
title = widget . get_title ( )
if title == " " :
title = self . cWebView . get_uri ( )
if title == " " : title = self . cLastUrl
self . set_title ( title + " - " + self . cTitle )
2021-12-20 05:46:31 +00:00
def cWebViewLoadChanged ( self , widget , event ) :
if event == WebKit2 . LoadEvent . STARTED :
self . cMenuLoadingIndication . show ( )
2021-12-19 03:59:42 +00:00
2021-12-20 05:46:31 +00:00
if event == WebKit2 . LoadEvent . FINISHED :
self . cMenuLoadingIndication . hide ( )
2021-12-19 03:59:42 +00:00
def cOpenWindow ( self , * args , * * kwargs ) :
browserWindows . append ( birdyBrowserWindow ( self . cWebView ) )
def cUrlEntryNavigate ( self , * args , * * kwargs ) :
url = self . cUrlEntry . get_text ( )
if len ( url . split ( " : " , 1 ) ) < 2 :
url = defaultProtocol + " :// " + url
self . set_focus ( self . cWebView )
2022-06-08 19:14:37 +00:00
if not singleProcessMode :
self . cWebView . destroy ( )
self . cCreateWebView ( False )
self . cResizeElements ( )
self . show_all ( )
2021-12-19 03:59:42 +00:00
self . cWebView . load_uri ( url )
browserWindows . append ( birdyBrowserWindow ( False ) )
Gtk . main ( )