{"id":24443694,"url":"https://github.com/endlessm/maxwell","last_synced_at":"2025-10-15T17:21:13.797Z","repository":{"id":149347142,"uuid":"125903052","full_name":"endlessm/maxwell","owner":"endlessm","description":"A WebKitWebView derived class that lets you embed GtkWidget","archived":false,"fork":false,"pushed_at":"2019-10-29T18:32:00.000Z","size":80,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-04-12T21:32:46.693Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/endlessm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-03-19T18:30:10.000Z","updated_at":"2023-09-30T14:52:48.000Z","dependencies_parsed_at":"2023-07-17T13:02:58.129Z","dependency_job_id":null,"html_url":"https://github.com/endlessm/maxwell","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/endlessm/maxwell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endlessm%2Fmaxwell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endlessm%2Fmaxwell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endlessm%2Fmaxwell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endlessm%2Fmaxwell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/endlessm","download_url":"https://codeload.github.com/endlessm/maxwell/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endlessm%2Fmaxwell/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279095498,"owners_count":26102333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-20T22:17:09.623Z","updated_at":"2025-10-15T17:21:13.786Z","avatar_url":"https://github.com/endlessm.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![Maxwell][logo]Embedding Gtk widgets in WebKit2\nA WebKitWebView derived class that lets you embed GtkWidget in it.\n\n### What is Maxwell?\nMaxwell is a proof of concept library that extends WebKitWebView and lets you\nembed/pack Gtk widgets in it as a regular Gtk container.\n\n### Etymology\nThe project started inspired by the [Broadway Gdk backend][gdk-broadway] which\nlets you run any Gtk application over HTTP using HTML5 and web sockets which\nwas named after [X Consortium's Broadway release][x11-broadway] where one of\nits key features was X-Agent 96.\n\nX Agent 96 =\u003e Agent 86 =\u003e Maxwell Smart =\u003e **Maxwell**\n\n### How does it work?\nThe introduction of the split process model in WebKit2 made embedding widgets\nin WebView rather difficult since part of WebKit operates in one process and\nthe rest like WebCore and JS engine in another (UI/Web process).\n\nMaxwell takes a similar approach to Broadway, all it needs is a way to render\nwidgets in the DOM tree and get events from them.\n\nTo render widgets we use a CANVAS element the same size of the widget and a\ncustom URI scheme to get the raw image data from each widget.\n\n```javascript\n/* Get image data from widget */\nlet xhr = new XMLHttpRequest();\nxhr.open('GET', 'maxwell:///widget_id', false);\nxhr.responseType = 'arraybuffer';\nxhr.send();\n\n/* Render image data in canvas */\nlet data = new Uint8ClampedArray(xhr.response);\nlet image = new ImageData(data, canvas.width, canvas.height);\ncanvas.getContext('2d').putImageData(image, 0, 0);\n```\n\nOn the Gtk side, each child is rendered in an offscreen window which we use as\nthe source image data to implement the custom URI scheme handler.\n\n| Gtk UI process                       | JavaScript/WebCore |\n| :----------------------------------: | :----------------: |\n| GtkWidget:draw↴                      |                    |\n| Damage event ⟶ JS child_draw()     ⟶ | GET maxwell://     |\n| URI handler                        ⟵ | ↲                  |\n| ↳[offscreen]⟶[GdkPixbuf]⟶GIOStream ⟶ | [ImageData]↴       |\n|                                      | putImageData()     |\n\nFor events all we have to do is properly implement GdkWindow::pick-embedded-child\nand let Gtk know which child widget should get the event.\nIn order to do so we need to keep track of the elements position relative to\nWebView's viewport which can be calculated with getBoundingClientRect().\n\n## API\n\nThe API is pretty straightforward, all you have to do is name the child widget\nand add it using regular GtkContainer API.\n```c\n/* Create a Maxwell Web View */\nwebview = maxwell_web_view_new ();\n\n/* Create a widget to embed */\nentry = gtk_entry_new ();\n\n/* Set a unique name on the widget */\ngtk_widget_set_name (entry, \"myentry\");\n\n/* Add widget to web view container */\ngtk_container_add (GTK_CONTAINER (webview), entry);\n```\nIn order for MaxwellWebView to know where to place a child in the DOM tree\nyou need to add a CANVAS element with a \"GtkWidget\" class and the unique ID\nyou used as the widget's name.\n```html\n\u003ccanvas class=\"GtkWidget\" id=\"myentry\"\u003e\u003c/canvas\u003e\n```\n\nMaxwell will also try to honor width and height style properties set on the\ncanvas element.\nSo for example if you want your widget to expand horizontally you can do:\n```html\n\u003ccanvas class=\"GtkWidget\" style=\"width: 100%;\" id=\"myentry\"\u003e\u003c/canvas\u003e\n```\n\n## Building\n * Install [meson] and [ninja]\n * `$ sudo apt-get install meson`\n * Create a build directory:\n * `$ mkdir _build \u0026\u0026 cd _build`\n * Run meson:\n * `$ meson`\n * Run ninja:\n * `$ ninja`\n * `$ sudo ninja install`\n\n## Licensing\nMaxwell is released under the terms of the GNU Lesser General Public License,\neither version 2.1 or, at your option, any later version.\n\n[logo]: https://github.com/endlessm/maxwell/blob/master/logo.svg\n[gdk-broadway]: https://developer.gnome.org/gtk3/stable/gtk-broadway.html\n[x11-broadway]: http://sunsite.uakom.sk/sunworldonline/swol-02-1997/swol-02-connectivity.html\n[meson]: http://mesonbuild.com/\n[ninja]: https://ninja-build.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fendlessm%2Fmaxwell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fendlessm%2Fmaxwell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fendlessm%2Fmaxwell/lists"}