Compare commits

...

66 Commits

Author SHA1 Message Date
ce069bdd73 tweak: add make uninstall, make clean 2023-03-28 11:44:54 -06:00
0b9386f5fe chore: add installation section to README.md 2023-03-28 11:42:59 -06:00
20d0becba9 chore: more upkeep. In particular, document wyebadblock better 2023-03-28 11:32:47 -06:00
37e3e7bcae tweak: delete config.def.h
it's a bit redundant, and no longer necessary once compatibility
with the original rose is no longer a goal
2023-03-28 11:19:55 -06:00
bbcf1dabd2 Revert "tweak: move things around"
This reverts commit ca59138a2a.
2023-03-28 11:19:11 -06:00
ca59138a2a tweak: move things around 2023-03-28 11:18:54 -06:00
cc959fda4f chore: more simplifications 2023-03-28 11:16:51 -06:00
18f4e3e3cb tweak: add formatter to makefile 2023-03-28 11:11:18 -06:00
1fca042b0b tweak: add rudimentary makefile 2023-03-28 10:59:38 -06:00
3483af0f0f style: enforce webkit style for plugins
$ clang-format -style=webkit -i */.c
$ clang-format -style=webkit -i */*/.c
2023-03-28 10:16:14 -06:00
ec97a8f3f3 style: start enforcing coding style
Previous .clang-format wasn't processed

$ clang-format -style=webkit -dump-config > .clang-format
$ clang-format -i rose.c
2023-03-28 10:14:13 -06:00
527d88efa6 Revert "tweak: resize screenshots"
This reverts commit 06a0d6d808.
2023-03-27 19:45:41 -06:00
aeb196837e Revert "tweak: resize screenshots again?"
This reverts commit bb4ba366ee.
2023-03-27 19:44:09 -06:00
bb4ba366ee tweak: resize screenshots again? 2023-03-27 19:43:19 -06:00
06a0d6d808 tweak: resize screenshots 2023-03-27 19:41:57 -06:00
1eb9f98dc8 tweak: change readme to point to screenshots 2023-03-27 19:37:35 -06:00
42c7565b7f tweak: save screenshots 2023-03-27 19:36:27 -06:00
7cecf5ae3a fix: rename filepath after dirchange 2023-03-27 19:34:01 -06:00
49df138b36 feat: rename after very strong simplification on the upstream rose
Compare with: <https://github.com/NunoSempere/rose-browser/tree/patch-1>
in Feb 7
2023-03-27 19:21:56 -06:00
ff033646cc tweak: add changes to README 2023-03-27 19:08:46 -06:00
0f4866f520 tweak: add tweak to remove annoying parts for Money Stuff 2023-02-27 15:29:30 -06:00
53cc700748 tweak: add custom user agent. 2023-02-15 20:34:17 +01:00
bcaad22c17 tweak: fihnish the readability upgrades for bloomberg 2023-02-15 18:46:07 +01:00
25dedb09e1 tweaks: around bloomberg webpage 2023-02-15 03:24:47 +01:00
a27b4357af tweak: add fancy quotes. 2023-02-15 03:23:57 +01:00
6a330e9b09 tweak: nicer blockquotes
also fix bug in archive.is / bloomberg.
2023-02-14 02:07:23 +01:00
86fef30c22 tweak: proton stylesheet 2023-02-11 14:40:42 +01:00
95829b06a2 tweak: tweak. desktop so that it opens links correctly 2023-02-09 16:31:33 +01:00
4f43648a84 tweak: update README 2023-02-08 14:31:28 +01:00
c10b7632eb feat: add possibility of launching many tabs at once.
also, personalize this:
- enable extensions
- change to my css
- change relative paths.

fix various bugs:
- set the zoom level in notebook_append, not in notebook_init
- have a handly debug option for valgrind
2023-02-08 14:29:36 +01:00
2db650d7cc tweak: enable all plugins. 2023-02-07 14:43:00 +01:00
33e4d0cdd1 tweak: todos 2023-02-07 14:41:58 +01:00
d1439d16f5 tweak: continue personal development from master. 2023-02-07 14:28:21 +01:00
b50d30851b fix: fix some warts
- stuff to deal with plugin code wasn't actually compiling
  - created a "stand_in" plugin to provide headers and function
definitions
  - when these are not used
  - it is likely there are better approaches here
- hidebar, newtab -> hide_bar, new_tab
2023-02-07 14:17:10 +01:00
fenze
35f968f29b
Merge pull request #38 from NunoSempere/patch-1
Tweak license mention in the readme
2023-02-07 12:49:54 +01:00
fenze
1ba5fd7ecd
Merge pull request #39 from davidovski/shell_fix
Remove bash-only features for sh scripts
2023-02-07 12:48:14 +01:00
davidovki
122437115d Remove bash-only features for sh scripts
Fix order of CC arguments to aid in linking on newer versions
2023-02-07 11:37:05 +00:00
08c19abc1d
Tweak license mention in the readme 2023-02-06 18:17:46 +01:00
fenze
4e0b961fcb
Merge pull request #37 from mini-rose/add-license-1
Create license
2023-02-06 18:09:16 +01:00
fenze
5b958d5faf
Create license 2023-02-06 18:08:24 +01:00
fenze
327344ee40
Merge pull request #36 from NunoSempere/feats-and-tweaks
Various feats and tweaks
2023-02-06 18:05:33 +01:00
b48c504871 feat: use flags rather than uncommenting code
- Significantly simpler
- Easier for me to keep up with upstream
- Alternatives:
  - Comments as before
  - git patches, as in the suckless community: eventually leads to
confusion about conflicting patches.
  - some other option
2023-02-05 03:57:29 +01:00
cbaa97a766 tweak: add shebangs. 2023-02-05 03:23:23 +01:00
353d0ffad7 feat: add plugin to customize css for individual websites...
and how to enable it.

Also tweak README.mds
2023-02-05 03:21:30 +01:00
be043958f0 feat: add readability mode, and explain how to enable it. 2023-02-05 03:13:12 +01:00
9a533b7e26 feat: disable plugins code by default and explain how to enable it. 2023-02-05 03:02:03 +01:00
6b3c830c3b tweak: add two style improvements that I consider unambiguous
1. Make top tab wider
2. Make tab title have a maximum width
2023-02-05 02:52:27 +01:00
4fd1c83660 tweak: add alternatives styles.css
also keep track in README of steps.
2023-02-05 02:48:25 +01:00
e928ee1c89 feat: add open in new tab functionality
for <a href=_blank... links, and when clicking on a link,
sometimes you want to open that link in a new tab.

This commit adds that functionality.
2023-02-05 02:31:57 +01:00
fenze
584a5d68a8 Fixed formatting in some libre_redirect files 2022-12-18 16:54:07 +00:00
fenze
d97045bf47 Add hidebar keybind 2022-12-18 16:42:50 +00:00
fenze
3325e17195
Merge pull request #32 from NunoSempere/ubuntu-20.04-scripts
tweak: add user scripts to get this running on ubuntu 20.04
2022-12-18 16:27:54 +00:00
fenze
b16665809c
Merge pull request #33 from NunoSempere/libre_redirect
feat: redirect websites to open-source frontends
2022-12-18 16:27:20 +00:00
f5d1c0f93d tweak: integrate "plugins" into build.sh 2022-12-17 20:54:47 +01:00
98abdb39c4 feat: integrate libre_redirect code into rose.c 2022-12-17 20:54:27 +01:00
6ff86dcc44 feat: redirect websites to open-source frontends
1. Adds code for redirecting annoying websites to their open-source
frontends, when these exist.

2. Organize this in a "plugins" folder
2022-12-17 20:47:44 +01:00
7ad3e023f8 tweak: add user scripts to get this running on ubuntu 20.04
I thought these might be useful. Feel free to not accept them,
though
2022-12-17 20:33:37 +01:00
fenze
62b1bd6785 Add newtab binding 2022-12-16 09:07:43 +00:00
fenze
055e50c9ef
Merge pull request #31 from NunoSempere/upstream
Some quality of life tweaks.
2022-12-13 18:15:35 +00:00
981c15bf93 feat: add less sucky duckduckgo homepage. 2022-12-13 16:33:04 +00:00
5ab887db47 trivial tweak: fix README layout error. 2022-12-13 15:31:36 +00:00
f6119ff7db tweak: Add reference to how to use normal browser controls. 2022-12-13 15:22:49 +00:00
5e403cad14 fix: small sh/bash incompatibility in rose-mklink
'echo -e' throws a warning in sh, but not in bash
2022-12-12 22:10:49 +00:00
1bed196381 tweak: suggest bg color for bright theme 2022-12-12 15:44:48 +00:00
a69d72f42b tweak: allow configurable width and height
and set a default of 500, 400
2022-12-12 15:38:48 +00:00
374128fccc tweak: boot up with the correct zoom 2022-12-12 15:37:31 +00:00
51 changed files with 3611 additions and 408 deletions

View File

@ -1,37 +0,0 @@
# vim:ft=yaml
IndentWidth: 8
BreakBeforeBraces: Linux
UseTab: Always
AlignArrayOfStructures: Left
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: True
AlwaysBreakBeforeMultilineStrings: True
BreakBeforeTernaryOperators: True
BreakStringLiterals: True
ColumnLimit: 100
IncludeBlocks: Regroup
KeepEmptyLinesAtTheStartOfBlocks: True
RemoveBracesLLVM: True
SortIncludes: CaseInsensitive
SortUsingDeclarations: True
SpaceAfterLogicalNot: True
SpaceAfterCStyleCast: True
SpaceAfterTemplateKeyword: False
PointerAlignment: Right
SpaceBeforeAssignmentOperators: True
SpaceBeforeCaseColon: False
SpaceBeforeCpp11BracedList: True
SpaceBeforeCtorInitializerColon: False
SpaceBeforeInheritanceColon: False
SpaceBeforeParens: Custom
SpaceBeforeParensOptions:
AfterControlStatements: True
AfterForeachMacros: True
AfterFunctionDeclarationName: False
AfterFunctionDefinitionName: False
AfterIfMacros: True
AfterOverloadedOperator: False
BeforeNonEmptyParentheses: False
SpaceBeforeRangeBasedForLoopColon: True

2
.gitignore vendored
View File

@ -1,3 +1 @@
rose
config.h
.clang-format

View File

@ -1,21 +1,73 @@
<h3 align=center> Rose Browser</h1>
<h4 align=center>Minimal browser based on webkit2gtk</h4>
## Rosenrot
#### Features
- tabs, cookies, caching
- minimal ui, autohiding elements
- ~400L code base
- custom gtk and websites css
- hackable without any knowledge
- builtin rose-mklink script for in-shell static links
A small browser forked from [rose](https://github.com/mini-rose/rose).
- Rose is a minimal browser based on webkit2gtk which aims to be a "basement for creating your own browser using [the] gtk and webkit libraries".
- Rosenrot is my fork from rose. It has accumulated cruft that I like, like a "readability" plugin that simplifies annoying websites like [Matt Levine's Money Stuff newsletter](https://www.bloomberg.com/opinion/articles/2022-10-18/matt-levine-s-money-stuff-credit-suisse-was-a-reverse-meme-stock).
- Rosenrot is also a song by the German hardcore rock band [Rammstein](https://www.youtube.com/watch?v=af59U2BRRAU).
You can see some screenshots in the [screenshots](./screenshots) folder.
### Features
- tabs, cookies, caching
- minimal ui, autohiding elements
- ~467L core code (the rose.c file)
- custom gtk and websites css
- builtin rose-mklink script for in-shell static links
- A few quality of life improvements.
- Optional adblocking through [wyebadblock](https://github.com/jun7/wyebadblock)
- Plugin system:
- Libre redirect: Redirect annoying websites to open source frontends
- Readability: Strip webpages of unnecessary elements for ease of reading with a custom shortcut
- Custom style: Override the css of predetermined websites
- Stand in plugin: Mimick function definitions which do nothing for the above plugins so that they can be quickly removed
### Installation
Install dependencies, then:
```
make build
make install # or sudo make install
```
You can also see more detailed instructions [here](./user-scripts/ubuntu-20.04/install-with-dependencies.sh), for Ubuntu 20.04 in particular—though they should generalize trivially.
#
### 👐 Contribute
See [contributing.md](https://github.com/mini-rose/rose/.github/contributing.md).
### 📜 License
Rose is released under own license, which grants the following permissions:
- Commercial use
- Distribution
- Modification
- Private use
- Contribute upstream to [github.com/mini-rose/rose](https://github.com/mini-rose/) for core functionality changes.
- Contribute here by sending a pull request on Github.
### To do
- [ ] Look at using relative rather than absolute paths
- [ ] Figure out if downloading files is doable.
- [ ] Figure out better way to have plugins
- [ ] Double check newtab/next-tab behavior
- [ ] Document stand_in.c better
- [ ] Find out what each of the css elements refers to.
- [ ] Use something other than Whatsapp as an example syslink.
- [ ] Set `webkit_web_context_set_sandbox_enabled` (<https://webkitgtk.org/reference/webkit2gtk/2.36.8/WebKitWebContext.html#webkit-web-context-set-sandbox-enabled>), as recommended here: <https://blogs.gnome.org/mcatanzaro/2022/11/04/stop-using-qtwebkit/>.
- [ ] Fix bug about distorted audio. Maybe related to <https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1547>
Done:
- [x] Mask user agent
- [x] Use a makefile.
- [x] Launch with more than one tab from command line
- [x] Figure out merge with upstream
- [x] String substitution on uri in order to redirect to better frontends.
- [x] Present "standard" browser keybindings as an alternative.
- [x] Fix zoom in new tab
- [x] Reader mode
- [x] Add reader mode to config.def.
- [x] Make tab bar slightly prettier.
- [x] Add "open in new window" functionality.
- Useful for opening links in new tab when clicking on them and selecting that option
- And for actually opening links with the href new_tab option.
- Links: <https://docs.gtk.org/gobject/func.signal_connect.html>, <https://webkitgtk.org/reference/webkit2gtk/2.37.90/signal.AutomationSession.create-web-view.html>, <https://webkitgtk.org/reference/webkit2gtk/2.26.0/WebKitWebView.html#WebKitWebView-create> <https://stackoverflow.com/questions/40180757/webkit2gtk-get-new-window-link>
### Known bugs
- [ ] Doesn't work with when Spanish is selected as the language, for some reason.

View File

@ -1,11 +0,0 @@
CC=clang
SRC=rose.c
DEPS=('webkit2gtk-4.0')
INCS=`pkg-config --cflags ${DEPS[@]}`
LIBS=`pkg-config --libs ${DEPS[@]}`
# Optional adblocking depends on https://github.com/jun7/wyebadblock
WYEBAB='-L/usr/lib/wyebrowser/adblock.so'
$CC $INCS $LIBS $SRC $WYEBAB -o rose

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2022 mini-rose
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and any associated documentation
* files to modify, copy, merge, publish, distribute and/or
* sublicense copies of this sotware for their own use.
* This code does not come with any warranty.
*
* Author: fenze <contact@fenze.dev>
*/
#include <gdk/gdkkeysyms.h>
/* See more:
* https://webkitgtk.org/reference/webkit2gtk/stable/class.Settings.html */
#define WEBKIT \
"enable-back-forward-navigation-gestures", true, "enable-developer-extras", true, \
"enable-smooth-scrolling", false
#define GTK "gtk-application-prefer-dark-theme", true, "gtk-enable-animations", false
#define HOME "https://duckduckgo.com"
#define SEARCH "https://duckduckgo.com/?q=%s"
#define CACHE_DIR "/home/fenze/.cache/rose"
#define KEY(x) GDK_KEY_##x
#define ZOOM 1 /* Starting zoom level */
#define ZOOM_VAL .1 /* Zooming value in zoomin/zoomout functions */
#define BG_COLOR "#1E1E2E"
typedef enum {
goback,
goforward,
refresh,
refresh_force,
back_to_home,
toggle_fullscreen,
zoomin,
zoomout,
zoom_reset,
next_tab,
prev_tab,
close_tab,
show_searchbar,
show_finder,
finder_next,
finder_prev
} func;
#define SFT 1 << 0
#define CTRL 1 << 2
#define ALT 1 << 3
static struct {
unsigned mod;
unsigned key;
func id;
} keys[] = {
{ CTRL, KEY(h), goback },
{ CTRL, KEY(l), goforward },
{ CTRL, KEY(r), refresh },
{ CTRL | SFT, KEY(R), refresh_force },
{ CTRL | SFT, KEY(H), back_to_home },
{ CTRL, KEY(equal), zoomin },
{ CTRL, KEY(minus), zoomout },
{ CTRL, KEY(0), zoom_reset },
{ ALT, KEY(h), prev_tab },
{ ALT, KEY(l), next_tab },
{ CTRL, KEY(w), close_tab },
{ 0x0, KEY(F11), toggle_fullscreen },
{ CTRL, KEY(e), show_searchbar },
{ CTRL, KEY(f), show_finder },
{ CTRL, KEY(n), finder_next },
{ CTRL | SFT, KEY(N), finder_prev }
};

99
config.h Normal file
View File

@ -0,0 +1,99 @@
#include <gdk/gdkkeysyms.h>
#include <stdbool.h>
/* See more:
* https://webkitgtk.org/reference/webkit2gtk/stable/class.Settings.html */
#define WEBKIT \
"enable-back-forward-navigation-gestures", true, "enable-developer-extras", true, \
"enable-smooth-scrolling", false
#define GTK "gtk-application-prefer-dark-theme", false, "gtk-enable-animations", false
#define ROSE_HOMEPAGE true
#define HOME ROSE_HOMEPAGE ? "file:///home/loki/Documents/core/software/fresh/C/rose-browser/rosenrot/user-scripts/ubuntu-20.04/rose-images/rose-homepage.png" : "https://lite.duckduckgo.com/html"
#define SEARCH "https://lite.duckduckgo.com/html/?q=%s"
#define CACHE_DIR "/home/loki/.cache/rose"
#define WIDTH 1920
#define HEIGHT 1080
#define KEY(x) GDK_KEY_##x
#define ZOOM 1.4 /* Starting zoom level.*/
#define ZOOM_VAL .1 /* Zooming value in zoomin/zoomout functions */
#define BG_COLOR "#FEFEFE" /* "FEFEFE", "#1E1E2E" */
#define DEBUG false
typedef enum {
goback,
goforward,
refresh,
refresh_force,
back_to_home,
toggle_fullscreen,
zoomin,
zoomout,
zoom_reset,
next_tab,
prev_tab,
close_tab,
show_searchbar,
show_finder,
finder_next,
finder_prev,
new_tab,
prettify,
hide_bar
} func;
#define SFT 1 << 0
#define CTRL 1 << 2
#define ALT 1 << 3
static struct {
unsigned mod;
unsigned key;
func id;
} keys[] = {
{ CTRL, KEY(h), goback },
{ CTRL, KEY(j), goforward },
{ CTRL, KEY(r), refresh },
{ CTRL | SFT, KEY(R), refresh_force },
{ CTRL | SFT, KEY(H), back_to_home },
{ CTRL, KEY(equal), zoomin },
{ CTRL, KEY(minus), zoomout },
{ CTRL, KEY(0), zoom_reset },
{ CTRL, KEY(Page_Up), prev_tab },
{ CTRL, KEY(Page_Down), next_tab },
{ CTRL, KEY(t), next_tab },
{ CTRL, KEY(w), close_tab },
{ 0x0, KEY(F11), toggle_fullscreen },
{ CTRL, KEY(l), show_searchbar },
{ CTRL, KEY(k), hide_bar },
{ CTRL, KEY(f), show_finder },
{ CTRL, KEY(n), finder_next },
{ CTRL | SFT, KEY(N), finder_prev },
{ CTRL, KEY(p), prettify }
};
/* ^ For controls more akin to normal browsers */
/* Reference for the key shorthand:
* <https://gitlab.gnome.org/GNOME/gtk/-/blob/main/gdk/gdkkeysyms.h> */
/* Old controls: {
{ CTRL, KEY(h), goback },
{ CTRL, KEY(l), goforward },
{ CTRL, KEY(r), refresh },
{ CTRL | SFT, KEY(R), refresh_force },
{ CTRL | SFT, KEY(H), back_to_home },
{ CTRL, KEY(equal), zoomin },
{ CTRL, KEY(minus), zoomout },
{ CTRL, KEY(0), zoom_reset },
{ ALT, KEY(h), prev_tab },
{ CTRL, KEY(k), hide_searchbar },
{ ALT, KEY(l), next_tab },
{ CTRL, KEY(w), close_tab },
{ 0x0, KEY(F11), toggle_fullscreen },
{ CTRL, KEY(e), show_searchbar },
{ CTRL, KEY(f), show_finder },
{ CTRL, KEY(n), finder_next },
{ CTRL | SFT, KEY(N), finder_prev },
{ CTRL, KEY(p), prettify }
};
*/

View File

@ -1,6 +0,0 @@
./build.sh && {
cp -f rose /usr/bin
mkdir -p /usr/share/themes/rose
cp style.css /usr/share/themes/rose/
cp rose-mklink /usr/bin
}

21
license Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-2023 Nuño Sempere
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

66
makefile Normal file
View File

@ -0,0 +1,66 @@
# make
# make build
# (sudo) make install
# make format
# make clean
# make uninstall
## C compiler
CC=clang
## Main file
SRC=rose.c
## Dependencies
DEPS='webkit2gtk-4.0'
DEBUG= #'-g'
INCS=`pkg-config --cflags ${DEPS}`
LIBS=`pkg-config --libs ${DEPS}`
## Optional adblocking
## depends on https://github.com/jun7/wyebadblock
ADBLOCK='-L/usr/lib/wyebrowser/adblock.so'
## Plugins
LIBRE_REDIRECT=./plugins/libre_redirect/libre_redirect.c ./plugins/libre_redirect/str_replace_start.c
READABILITY=./plugins/readability/readability.c
CUSTOM_STYLES=./plugins/style/style.c
STAND_IN=./plugins/stand_in/stand_in.c # gives function definitions for the above, which do nothing
PLUGS=$(LIBRE_REDIRECT) $(READABILITY) $(CUSTOM_STYLES)
# PLUGS=$(STAND_IN)
# Note that if you want some plugins but not others,
# You should edit the stand_in.c file
# CONFIG
CONFIG=config.h
# cp -f config.def.h config.h
## Formatter
STYLE_BLUEPRINT=webkit
FORMATTER=clang-format -i -style=$(STYLE_BLUEPRINT)
## Commands
build: $(SRC) $(PLUGS) $(CONFIG)
$(CC) $(DEBUG) $(INCS) $(PLUGS) $(SRC) -o rose $(LIBS) $(ADBLOCK)
install: rose
cp -f rose /usr/bin
mkdir -p /usr/share/themes/rose
cp style.css /usr/share/themes/rose/
cp rose-mklink /usr/bin
uninstall:
rm -r /usr/share/themes/rose
rm /usr/bin/rose
rm /usr/bin/rose-mklink
clean:
rm rose
format: $(SRC) $(PLUGS)
$(FORMATTER) $(SRC) $(PLUGS)

View File

@ -0,0 +1,3 @@
## About
This code automatically redirects webpage to their open-source frontends. It is based on <https://libredirect.codeberg.page/>

View File

@ -0,0 +1,84 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "str_replace_start.h"
#define LIBRE_N 19
/* Uncomment for debug */
/* #define DEBUG */
/* Inspired by https://libredirect.github.io/, but in C. */
void str_init(char* str, int n)
{
for (int i = 0; i < n; i++)
str[i] = ' ';
str[n] = '\0';
} // could also use <https://manpages.ubuntu.com/manpages/impish/man3/strinit.3pub.html>
int libre_redirect(const char* uri, char* output)
{
int l1 = strlen(uri);
int l2 = strlen(output);
int len;
char tmp_uri[l2++];
char tmp_output[l2++];
if ((l2 - l1) < LIBRE_N) {
#ifdef DEBUG
printf("Not enough memory\n");
#endif
return 1; // not enough memory.
} else {
strcpy(tmp_uri, uri); // strcpy also copies the terminating '\0'
strcpy(tmp_output, output);
char* annoying_sites[] = {
"https://www.youtube.com",
"https://www.reddit.com",
"https://medium.com",
"https://translate.google.com",
// "https://forum.effectivealtruism.org",
"https://www.bloomberg.com",
"https://twitter.com"
};
char* alternatives[] = {
"https://yt.artemislena.eu",
"https://teddit.nunosempere.com",
"https://scribe.rip",
"https://simplytranslate.org/",
// "https://ea.greaterwrong.com",
"https://archive.is/https://www.bloomberg.com",
"https://nitter.net"
};
len = sizeof(annoying_sites) / sizeof(annoying_sites[0]);
for (int i = 0; i < len; i++) {
int replace_check = str_replace_start(tmp_uri, annoying_sites[i],
alternatives[i], output);
if (replace_check == 2) {
#ifdef DEBUG
printf("tmp_uri: %s\n", tmp_uri);
printf("output: %s\n", output);
#endif
return 2;
} else if (replace_check == 1) {
#ifdef DEBUG
printf("replace_check failed\n");
#endif
return 1;
}
strcpy(tmp_uri, output);
str_init(output, l2);
}
strcpy(output, tmp_uri);
}
#ifdef DEBUG
printf("No match found\n\n");
#endif
return 0;
}

View File

@ -0,0 +1,6 @@
#pragma once
#define LIBRE_N 19
int libre_redirect(const char* uri, char* uri_filtered);
void str_init(char* str, int n);

View File

@ -0,0 +1,65 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define DEBUG false
/*
See also:
* <https://web.archive.org/web/20160201212501/coding.debuntu.org/c-implementing-str_replace-replace-all-occurrences-substring>
* https://github.com/irl/la-cucina/blob/master/str_replace.c
*/
int str_replace_start(const char* string, const char* target, const char* replacement, char* output)
{
int l1 = strlen(string);
int l2 = strlen(target);
int l3 = strlen(replacement);
int l4 = strlen(output);
if (DEBUG)
printf("%d,%d,%d,%d\n", l1, l2, l3, l4);
// if(DEBUG) printf("%s,%s,%s,%s\n", string, target, replacement, output);
if ((l4 < (l1 - l2 + l3)) || l4 < l1) {
// Not enough memory in output string.
if (DEBUG)
printf("String not long enough.\n");
return 1;
}
/* else if(l1 < l2){
// Not even possible that there is a match.
if(DEBUG) printf("Target larger than string.\n");
strcpy(output, string);
} */
else {
if (DEBUG)
printf("Looking for a match for %s in %s.\n", target, string);
int match = true;
for (int i = 0; i < l2; i++) {
if (string[i] != target[i]) {
match = false;
break;
}
}
if (match) {
if (DEBUG)
printf("Found match.\n");
for (int i = 0; i < l3; i++) {
output[i] = replacement[i];
}
int counter = l3;
for (int i = l2; i < l1; i++) {
output[counter] = string[i];
counter++;
}
output[counter] = '\0';
return 2; // success
} else {
if (DEBUG)
printf("Did not find match.\n");
strcpy(output, string);
}
}
return 0;
}

View File

@ -0,0 +1,4 @@
#pragma once
int str_replace_start(const char* string, const char* target,
const char* replacement, char* output);

View File

@ -0,0 +1,11 @@
#!/bin/bash
CC=gcc
FLAGS="-std=c99 -Wall -lm"
SRC=example.c
REQS="../str_replace_start.c ../libre_redirect.c"
echo -e "\n\n\n"
$CC $FLAGS $SRC $REQS -o example

View File

@ -0,0 +1,19 @@
#include "../libre_redirect.h"
#include <stdio.h>
#include <string.h>
int main()
{
char uri[] = "https://reddit.com/r/blah";
int l = LIBRE_N + strlen(uri) + 1;
char uri_filtered[l];
str_init(uri_filtered, l);
if (!libre_redirect(uri, uri_filtered)) {
printf("Filtered uri: %s\n", uri_filtered);
} else {
printf("Uri: %s\n", uri);
// failure; do something with the original uri.
}
}

View File

@ -0,0 +1,2 @@
This code reimplements firefox readability mode. Code taken from <https://raw.githubusercontent.com/ushnisha/readability-reader-webextensions/master/content_scripts/tranquilize.js>

BIN
plugins/readability/readability Executable file

Binary file not shown.

View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define READABILITY_N 85133 + 1000
void read_readability_js(char* string)
{
FILE* fp = fopen("/home/loki/Documents/core/software/fresh/C/rose-browser/rosenrot/plugins/readability/readability.js", "r");
if (!fp) { // fp is NULL, fopen failed
fprintf(stderr, "Failed to open file\n");
string = NULL;
return;
}
int i = 0;
int c;
while ((c = fgetc(fp)) != EOF) {
string[i++] = c;
}
string[i] = '\0';
fclose(fp);
}
/*
int main(){
char* readability_js = malloc(READABILITY_N+1);
read_readability_js(readability_js);
printf("%s", readability_js);
free(readability_js);
}
*/

View File

@ -0,0 +1,8 @@
#ifndef READABILITY
#define READABILITY
#define READABILITY_N 85133 + 1000
void read_readability_js(char* string);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#!/bin/bash
function sedr(){
find ./ -type f -exec sed -i -e "$1" {} \;
} ## e.g., sedr "s/target/replacement/g"
READABILITY_N=$(wc -c readability.js | cut -d " " -f 1)
sedr "s/^#define READABILITY_N .*/#define READABILITY_N $READABILITY_N + 1000/g"

View File

@ -0,0 +1,27 @@
/* Why this file is needed:
* If the plugins are disabled,
* their conditionals will never resolve
* and their functionality never comes into play
* but the compiler still wants to know their type
*/
int libre_redirect(const char* uri, char* uri_filtered){
return 0;
}
void str_init(char* str, int n){
};
int str_replace_start(const char* string, const char* target,
const char* replacement, char* output){
return 1;
};
void read_readability_js(char* string){
}
void read_style_js(char* string){
}

View File

@ -0,0 +1,23 @@
/* Why this file is needed:
* If the plugins are disabled,
* their conditionals will never resolve
* and their functionality never comes into play
* but the compiler still wants to know their type
*/
#pragma once
#define LIBRE_N 0
#define STYLE_N 0
#define READABILITY_N 84638 + 1
int libre_redirect(const char* uri, char* uri_filtered);
void str_init(char* str, int n);
int str_replace_start(const char* string, const char* target,
const char* replacement, char* output);
void read_readability_js(char* string);
void read_style_js(char* string);

5
plugins/style/README.md Normal file
View File

@ -0,0 +1,5 @@
## Customize css style for individual websites.
- Replicates: <https://addons.mozilla.org/en-GB/firefox/addon/styl-us/>.
- The template is similar to the readability folder.
- You will also want to customize the `style.c` file.

View File

@ -0,0 +1,8 @@
#!/bin/bash
function sedr(){
find ./ -type f -exec sed -i -e "$1" {} \;
} ## e.g., sedr "s/target/replacement/g"
STYLE_N=$(wc -c style.js | cut -d " " -f 1)
sedr "s/^#define STYLE_N .*/#define STYLE_N $STYLE_N + 1/g"

30
plugins/style/style.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STYLE_N 1393 + 1
void read_style_js(char* string)
{
FILE* fp = fopen("/home/loki/Documents/core/software/fresh/C/rose-browser/rosenrot/plugins/style/style.js", "r");
if (!fp) { // fp is NULL, fopen failed
fprintf(stderr, "Failed to open file\n");
string = NULL;
return;
}
int i = 0;
int c;
while ((c = fgetc(fp)) != EOF) {
string[i++] = c;
}
string[i] = '\0';
fclose(fp);
}
/*
int main(){
char* readability_js = malloc(STYLE_N+1);
read_readability_js(readability_js);
printf("%s", readability_js);
free(readability_js);
}
*/

8
plugins/style/style.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef STYLE
#define STYLE
#define STYLE_N 1393 + 1
void read_style_js(char* string);
#endif

49
plugins/style/style.js Normal file
View File

@ -0,0 +1,49 @@
// Replicates the Stylus app: <https://addons.mozilla.org/en-GB/firefox/addon/styl-us/>
var styles = null;
if (document.domain == "forum.effectivealtruism.org"){
styles = `
.Layout-main {
margin-left: 100px;
}
.SingleColumnSection-root {
width: 1000px !important;
max-width: 1400px !important;
padding-left: 100px !important;
}
.NavigationStandalone-sidebar {
display: none;
}
.intercom-lightweight-app{
display: none;
}
`
var styleSheet = document.createElement('style')
styleSheet.innerText = styles
document.head.appendChild(styleSheet)
console.log('Style changed')
}
if (document.domain == "mail.proton.me" ){
styles = `
.item-container-row.read, .item-container.read {
background-color: white;
}
.item-container-row.unread, .item-container.unread {
background-color: #E8E8E8;
}
.selection .item-container-row.item-is-selected, .item-container.item-is-selected {
background-color: var(--selection-background-color) !important;
}
`
}
if(styles != null){
var styleSheet = document.createElement('style')
styleSheet.innerText = styles
document.head.appendChild(styleSheet)
console.log('Style changed')
}
document.body.style.visibility = "visible"

View File

@ -1,17 +1,17 @@
#!/bin/sh
test "$1" = "--help" || test -z "$1" && {
echo -e "usage: rose-mklink <alias> <url>\n"
echo "Create a /usr/bin link to a website."
printf "%s\n" "usage: rose-mklink <alias> <url>" \
"Create a /usr/bin link to a website."
exit
}
test -z "$2" || {
[ -f "/usr/bin/$1" ] && {
test -f "/usr/bin/$1" && {
echo "/usr/bin/$1 already exists, remove it first"
exit 1
}
echo -e "#!/bin/sh\n\nrose $2" > /usr/bin/$1
printf "#!/bin/sh\n\nrose %s" "$2" > /usr/bin/$1
chmod +x /usr/bin/$1
}

653
rose.c
View File

@ -1,316 +1,463 @@
/*
* Copyright (c) 2022 mini-rose
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and any associated documentation
* files to modify, copy, merge, publish, distribute and/or
* sublicense copies of this sotware for their own use.
* This code does not come with any warranty.
*
* Author: fenze <contact@fenze.dev>
*/
#include <stdbool.h>
#include <stdlib.h> // necessary for free, malloc.
#include <string.h>
#include <webkit2/webkit2.h>
#include "config.h"
#include <webkit2/webkit2.h>
#include "plugins/libre_redirect/libre_redirect.h"
#include "plugins/readability/readability.h"
#include "plugins/style/style.h"
#define CACHE \
"base-cache-directory", CACHE_DIR, \
"base-data-directory", CACHE_DIR, \
"disk-cache-directory", CACHE_DIR, \
"dom-cache-directory", CACHE_DIR, \
"hsts-cache-directory", CACHE_DIR, \
"indexeddb-directory", CACHE_DIR, \
"itp-directory", CACHE_DIR, \
"local-storage-directory", CACHE_DIR, \
"offline-application-cache-directory", CACHE_DIR, \
"service-worker-registrations-directory", CACHE_DIR
// #include "plugins/stand_in/stand_in.h"
enum { _SEARCH, _FIND };
int LIBRE_REDIRECT_ENABLED = true;
int READABILITY_ENABLED = true;
int CUSTOM_STYLE_ENABLED = true;
int CUSTOM_USER_AGENT = true;
// to enable plugins,
// 1. Enable them:
// - uncomment their #include statement
// - set their variable to true
// - in build.sh, uncomment: REQS= #./plugins/*/*.c
// 2. Remove stand_in code;
// - Comment out #include "plugins/stand_in/stand_in.h" line, or edit it
// together with stand_in.c so as to not include the plugin functions.
// - In build.sh, comment out REQS=./plugins/stand_in/stand_in.c
#define CACHE \
"base-cache-directory", CACHE_DIR, "base-data-directory", CACHE_DIR, \
"disk-cache-directory", CACHE_DIR, "dom-cache-directory", CACHE_DIR, \
"hsts-cache-directory", CACHE_DIR, "indexeddb-directory", CACHE_DIR, \
"itp-directory", CACHE_DIR, "local-storage-directory", CACHE_DIR, \
"offline-application-cache-directory", CACHE_DIR, \
"service-worker-registrations-directory", CACHE_DIR
enum { _SEARCH,
_FIND,
_HIDDEN };
static int entry_mode;
static GtkWindow *window;
static GtkHeaderBar *bar;
static GtkEntryBuffer *search_buf;
static GtkEntry *search;
static GtkWindow* window;
static GtkHeaderBar* bar;
static GtkEntryBuffer* search_buf;
static GtkEntry* search;
WebKitWebView *webview_new()
WebKitWebView* webview_new()
{
char *style;
WebKitSettings *settings;
WebKitWebContext *web_context;
WebKitCookieManager *cookiemanager;
WebKitUserContentManager *contentmanager;
char* style;
WebKitSettings* settings;
WebKitWebContext* web_context;
WebKitCookieManager* cookiemanager;
WebKitUserContentManager* contentmanager;
settings = webkit_settings_new_with_settings(WEBKIT, NULL);
web_context = webkit_web_context_new_with_website_data_manager(
webkit_website_data_manager_new(CACHE, NULL));
contentmanager = webkit_user_content_manager_new();
cookiemanager = webkit_web_context_get_cookie_manager(web_context);
settings = webkit_settings_new_with_settings(WEBKIT, NULL);
if (CUSTOM_USER_AGENT) {
webkit_settings_set_user_agent(
settings,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, "
"like Gecko) Chrome/110.0.0.0 Safari/537.36");
// See: <https://www.useragents.me/> for some common user agents
}
web_context = webkit_web_context_new_with_website_data_manager(
webkit_website_data_manager_new(CACHE, NULL));
contentmanager = webkit_user_content_manager_new();
cookiemanager = webkit_web_context_get_cookie_manager(web_context);
webkit_cookie_manager_set_persistent_storage(cookiemanager, CACHE_DIR "/cookies.sqlite",
WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
webkit_cookie_manager_set_persistent_storage(
cookiemanager, CACHE_DIR "/cookies.sqlite",
WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
webkit_cookie_manager_set_accept_policy(cookiemanager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
webkit_cookie_manager_set_accept_policy(cookiemanager,
WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
webkit_web_context_set_process_model(web_context,
WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
webkit_web_context_set_process_model(
web_context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
if (g_file_get_contents("~/.config/rose/style.css", &style, NULL, NULL))
webkit_user_content_manager_add_style_sheet(
contentmanager,
webkit_user_style_sheet_new(style, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
WEBKIT_USER_STYLE_LEVEL_USER, NULL, NULL));
if (g_file_get_contents("~/.config/rose/style.css", &style, NULL, NULL))
webkit_user_content_manager_add_style_sheet(
contentmanager, webkit_user_style_sheet_new(style, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, NULL, NULL));
return g_object_new(WEBKIT_TYPE_WEB_VIEW, "settings", settings, "web-context", web_context,
"user-content-manager", contentmanager, NULL);
return g_object_new(WEBKIT_TYPE_WEB_VIEW, "settings", settings, "web-context",
web_context, "user-content-manager", contentmanager,
NULL);
}
void load_uri(WebKitWebView *view, const char *uri)
WebKitWebView* notebook_get_webview(GtkNotebook* notebook)
{
if (g_str_has_prefix(uri, "http://") || g_str_has_prefix(uri, "https://") ||
g_str_has_prefix(uri, "file://") || g_str_has_prefix(uri, "about:")) {
webkit_web_view_load_uri(view, uri);
} else {
char tmp[strlen(uri) + strlen(SEARCH)];
snprintf(tmp, sizeof(tmp), SEARCH, uri);
webkit_web_view_load_uri(view, tmp);
}
return WEBKIT_WEB_VIEW(gtk_notebook_get_nth_page(
notebook, gtk_notebook_get_current_page(notebook)));
}
void load_changed(WebKitWebView *self, WebKitLoadEvent load_event, GtkNotebook *notebook)
void load_uri(WebKitWebView* view, const char* uri)
{
if (load_event == WEBKIT_LOAD_FINISHED) {
gtk_notebook_set_tab_label_text(notebook, GTK_WIDGET(self),
webkit_web_view_get_title(self));
gtk_widget_hide(GTK_WIDGET(bar));
}
if (g_str_has_prefix(uri, "http://") || g_str_has_prefix(uri, "https://") || g_str_has_prefix(uri, "file://") || g_str_has_prefix(uri, "about:")) {
webkit_web_view_load_uri(view, uri);
} else {
// webkit_web_view_load_uri(view, uri);
char tmp[strlen(uri) + strlen(SEARCH)];
snprintf(tmp, sizeof(tmp), SEARCH, uri);
webkit_web_view_load_uri(view, tmp);
}
}
void notebook_append(GtkNotebook *notebook, const char *uri)
void redirect_if_annoying(WebKitWebView* view, const char* uri)
{
GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(window));
GdkVisual *rgba_visual = gdk_screen_get_rgba_visual(screen);
GdkRGBA rgba;
int l = LIBRE_N + strlen(uri) + 1;
char uri_filtered[l];
str_init(uri_filtered, l);
gdk_rgba_parse(&rgba, BG_COLOR);
int check = libre_redirect(uri, uri_filtered);
WebKitWebView *view = webview_new();
gtk_widget_set_visual(GTK_WIDGET(window), rgba_visual);
g_signal_connect(view, "load_changed", G_CALLBACK(load_changed), notebook);
int n = gtk_notebook_append_page(notebook, GTK_WIDGET(view), NULL);
gtk_notebook_set_tab_reorderable(notebook, GTK_WIDGET(view), true);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_widget_hide(GTK_WIDGET(bar));
webkit_web_view_set_background_color(view, &rgba);
load_uri(view, (uri) ? uri : HOME);
gtk_notebook_set_current_page(notebook, n);
if (check == 2) {
webkit_web_view_load_uri(view, uri_filtered);
}
}
WebKitWebView *notebook_get_webview(GtkNotebook *notebook)
void load_changed(WebKitWebView* self, WebKitLoadEvent load_event,
GtkNotebook* notebook)
{
return WEBKIT_WEB_VIEW(
gtk_notebook_get_nth_page(notebook, gtk_notebook_get_current_page(notebook)));
switch (load_event) {
/* see <https://webkitgtk.org/reference/webkit2gtk/2.5.1/WebKitWebView.html>
*/
case WEBKIT_LOAD_STARTED:
if (CUSTOM_STYLE_ENABLED) {
char* style_js = malloc(STYLE_N + 1);
read_style_js(style_js);
webkit_web_view_run_javascript(notebook_get_webview(notebook), style_js,
NULL, NULL, NULL);
free(style_js);
}
if (LIBRE_REDIRECT_ENABLED) {
redirect_if_annoying(self, webkit_web_view_get_uri(self));
}
break;
case WEBKIT_LOAD_REDIRECTED:
if (LIBRE_REDIRECT_ENABLED) {
redirect_if_annoying(self, webkit_web_view_get_uri(self));
}
break;
case WEBKIT_LOAD_COMMITTED:
if (LIBRE_REDIRECT_ENABLED) {
redirect_if_annoying(self, webkit_web_view_get_uri(self));
}
if (CUSTOM_STYLE_ENABLED) {
char* style_js = malloc(STYLE_N + 1);
read_style_js(style_js);
webkit_web_view_run_javascript(notebook_get_webview(notebook), style_js,
NULL, NULL, NULL);
free(style_js);
}
break;
case WEBKIT_LOAD_FINISHED: {
/* Add gtk tab title */
const char* webpage_title = webkit_web_view_get_title(self);
const int max_length = 25;
char tab_title[max_length + 1];
if (webpage_title != NULL) {
for (int i = 0; i < (max_length); i++) {
tab_title[i] = webpage_title[i];
if (webpage_title[i] == '\0') {
break;
}
}
tab_title[max_length] = '\0';
}
gtk_notebook_set_tab_label_text(notebook, GTK_WIDGET(self),
webpage_title == NULL ? "" : tab_title);
// gtk_widget_hide(GTK_WIDGET(bar));
}
}
}
void show_bar(GtkNotebook *notebook)
{
if (entry_mode == _SEARCH) {
const char *url = webkit_web_view_get_uri(notebook_get_webview(notebook));
gtk_entry_set_placeholder_text(search, "Search");
gtk_entry_buffer_set_text(search_buf, url, strlen(url));
gtk_widget_show(GTK_WIDGET(bar));
gtk_window_set_focus(window, GTK_WIDGET(search));
} else {
const char *search_text = webkit_find_controller_get_search_text(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
void notebook_append(GtkNotebook* notebook, const char* uri);
/* notebook_append calls handle_create, but handle_create also calls
* notebook_append. Therefore we need to declare notebook_append, so that
* handle_create_new_tab knows its type.
*/
if (search_text != NULL)
gtk_entry_buffer_set_text(search_buf, search_text, strlen(search_text));
gtk_entry_set_placeholder_text(search, "Find");
gtk_widget_show(GTK_WIDGET(bar));
gtk_window_set_focus(window, GTK_WIDGET(search));
}
GtkWidget* handle_create_new_tab(WebKitWebView* self,
WebKitNavigationAction* navigation_action,
GtkNotebook* notebook)
{
WebKitURIRequest* uri_request = webkit_navigation_action_get_request(navigation_action);
const char* uri = webkit_uri_request_get_uri(uri_request);
printf("Creating new window: %s\n", uri);
notebook_append(notebook, uri);
gtk_notebook_set_show_tabs(notebook, true);
return NULL;
/* WebKitGTK documentation recommends returning the new webview.
* I imagine that this might allow e.g., to go back in a new tab
* or generally to keep track of history.
* However, this would require either modifying notebook_append
* or duplicating its contents, for unclear gain.
*/
}
int handle_key(func id, GtkNotebook *notebook)
void notebook_append(GtkNotebook* notebook, const char* uri)
{
static double zoom = ZOOM;
static bool is_fullscreen = 0;
GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(window));
GdkVisual* rgba_visual = gdk_screen_get_rgba_visual(screen);
GdkRGBA rgba;
switch (id) {
case goback:
webkit_web_view_go_back(notebook_get_webview(notebook));
break;
case goforward:
webkit_web_view_go_forward(notebook_get_webview(notebook));
break;
gdk_rgba_parse(&rgba, BG_COLOR);
case refresh:
webkit_web_view_reload(notebook_get_webview(notebook));
break;
case refresh_force:
webkit_web_view_reload_bypass_cache(notebook_get_webview(notebook));
break;
WebKitWebView* view = webview_new();
case back_to_home:
load_uri(notebook_get_webview(notebook), HOME);
break;
gtk_widget_set_visual(GTK_WIDGET(window), rgba_visual);
g_signal_connect(view, "load_changed", G_CALLBACK(load_changed), notebook);
g_signal_connect(view, "create", G_CALLBACK(handle_create_new_tab), notebook);
case zoomin:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook), (zoom += ZOOM_VAL));
break;
case zoomout:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook), (zoom -= ZOOM_VAL));
break;
case zoom_reset:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook), (zoom = ZOOM));
break;
case prev_tab:
if (gtk_notebook_get_current_page(notebook) == 0) {
gtk_notebook_set_current_page(notebook,
gtk_notebook_get_n_pages(notebook) - 1);
} else {
gtk_notebook_prev_page(notebook);
}
break;
case next_tab:
if (gtk_notebook_get_current_page(notebook) ==
gtk_notebook_get_n_pages(notebook) - 1) {
notebook_append(notebook, NULL);
gtk_notebook_set_show_tabs(notebook, true);
} else {
gtk_notebook_next_page(notebook);
}
break;
case close_tab:
gtk_notebook_remove_page(notebook, gtk_notebook_get_current_page(notebook));
switch (gtk_notebook_get_n_pages(notebook)) {
case 0:
exit(0);
break;
case 1:
gtk_notebook_set_show_tabs(notebook, false);
break;
}
break;
case toggle_fullscreen:
if (is_fullscreen)
gtk_window_unfullscreen(window);
else
gtk_window_fullscreen(window);
is_fullscreen = ! is_fullscreen;
break;
case show_searchbar:
entry_mode = _SEARCH;
show_bar(notebook);
break;
case show_finder:
entry_mode = _FIND;
show_bar(notebook);
break;
case finder_next:
webkit_find_controller_search_next(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
break;
case finder_prev:
webkit_find_controller_search_previous(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
break;
}
return 1;
int n = gtk_notebook_append_page(notebook, GTK_WIDGET(view), NULL);
gtk_notebook_set_tab_reorderable(notebook, GTK_WIDGET(view), true);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_widget_hide(GTK_WIDGET(bar));
webkit_web_view_set_background_color(view, &rgba);
load_uri(view, (uri) ? uri : HOME);
gtk_notebook_set_current_page(notebook, n);
gtk_notebook_set_tab_label_text(notebook, GTK_WIDGET(view), "-");
webkit_web_view_set_zoom_level(view, ZOOM);
}
int keypress(void *self, GdkEvent *e, GtkNotebook *notebook)
void show_bar(GtkNotebook* notebook)
{
(void) self;
if (entry_mode == _SEARCH) {
const char* url = webkit_web_view_get_uri(notebook_get_webview(notebook));
gtk_entry_set_placeholder_text(search, "Search");
gtk_entry_buffer_set_text(search_buf, url, strlen(url));
gtk_widget_show(GTK_WIDGET(bar));
gtk_window_set_focus(window, GTK_WIDGET(search));
} else if (entry_mode == _HIDDEN) {
gtk_widget_hide(GTK_WIDGET(bar));
} else {
const char* search_text = webkit_find_controller_get_search_text(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
for (int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++)
if (e->key.keyval == keys[i].key && e->key.state == keys[i].mod)
return handle_key(keys[i].id, notebook);
if (search_text != NULL)
gtk_entry_buffer_set_text(search_buf, search_text, strlen(search_text));
return 0;
gtk_entry_set_placeholder_text(search, "Find");
gtk_widget_show(GTK_WIDGET(bar));
gtk_window_set_focus(window, GTK_WIDGET(search));
}
}
void search_activate(GtkEntry *self, GtkNotebook *notebook)
int handle_key(func id, GtkNotebook* notebook)
{
if (entry_mode == _SEARCH)
load_uri(notebook_get_webview(notebook), gtk_entry_buffer_get_text(search_buf));
else if (entry_mode == _FIND)
webkit_find_controller_search(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)),
gtk_entry_buffer_get_text(search_buf),
WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | WEBKIT_FIND_OPTIONS_WRAP_AROUND,
G_MAXUINT);
static double zoom = ZOOM;
static bool is_fullscreen = 0;
gtk_widget_hide(GTK_WIDGET(bar));
switch (id) {
case goback:
webkit_web_view_go_back(notebook_get_webview(notebook));
break;
case goforward:
webkit_web_view_go_forward(notebook_get_webview(notebook));
break;
case refresh:
webkit_web_view_reload(notebook_get_webview(notebook));
break;
case refresh_force:
webkit_web_view_reload_bypass_cache(notebook_get_webview(notebook));
break;
case back_to_home:
load_uri(notebook_get_webview(notebook), HOME);
break;
case zoomin:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook),
(zoom += ZOOM_VAL));
break;
case zoomout:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook),
(zoom -= ZOOM_VAL));
break;
case zoom_reset:
webkit_web_view_set_zoom_level(notebook_get_webview(notebook),
(zoom = ZOOM));
break;
case prev_tab:
if (gtk_notebook_get_current_page(notebook) == 0) {
gtk_notebook_set_current_page(notebook,
gtk_notebook_get_n_pages(notebook) - 1);
} else {
gtk_notebook_prev_page(notebook);
}
break;
case next_tab:
if (gtk_notebook_get_current_page(notebook) == gtk_notebook_get_n_pages(notebook) - 1) {
notebook_append(notebook, NULL);
gtk_notebook_set_show_tabs(notebook, true);
webkit_web_view_set_zoom_level(notebook_get_webview(notebook), zoom);
} else {
gtk_notebook_next_page(notebook);
}
break;
case close_tab:
gtk_notebook_remove_page(notebook, gtk_notebook_get_current_page(notebook));
switch (gtk_notebook_get_n_pages(notebook)) {
case 0:
exit(0);
break;
case 1:
gtk_notebook_set_show_tabs(notebook, false);
break;
}
break;
case toggle_fullscreen:
if (is_fullscreen)
gtk_window_unfullscreen(window);
else
gtk_window_fullscreen(window);
is_fullscreen = !is_fullscreen;
break;
case show_searchbar:
entry_mode = _SEARCH;
show_bar(notebook);
break;
case show_finder:
entry_mode = _FIND;
show_bar(notebook);
break;
case finder_next:
webkit_find_controller_search_next(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
break;
case finder_prev:
webkit_find_controller_search_previous(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)));
break;
case new_tab:
notebook_append(notebook, NULL);
gtk_notebook_set_show_tabs(notebook, true);
entry_mode = _SEARCH;
show_bar(notebook);
break;
case hide_bar:
entry_mode = _HIDDEN;
show_bar(notebook);
break;
case prettify: {
if (READABILITY_ENABLED) {
char* readability_js = malloc(READABILITY_N + 1);
read_readability_js(readability_js);
webkit_web_view_run_javascript(notebook_get_webview(notebook),
readability_js, NULL, NULL, NULL);
free(readability_js);
}
break;
}
}
return 1;
}
void window_init(GtkNotebook *notebook)
int keypress(void* self, GdkEvent* e, GtkNotebook* notebook)
{
GtkCssProvider *css = gtk_css_provider_new();
(void)self;
gtk_css_provider_load_from_path(css, "/usr/share/themes/rose/style.css", NULL);
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(css),
800);
for (int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++)
if (e->key.keyval == keys[i].key && e->key.state == keys[i].mod)
return handle_key(keys[i].id, notebook);
gtk_entry_buffer_new("", 0);
gtk_entry_set_alignment(search, 0.48);
gtk_widget_set_size_request(GTK_WIDGET(search), 300, -1);
gtk_header_bar_set_custom_title(bar, GTK_WIDGET(search));
gtk_window_set_titlebar(window, GTK_WIDGET(bar));
g_signal_connect(search, "activate", G_CALLBACK(search_activate), notebook);
g_signal_connect(window, "key-press-event", G_CALLBACK(keypress), notebook);
g_signal_connect(window, "destroy", G_CALLBACK(exit), notebook);
return 0;
}
void notebook_init(GtkNotebook *notebook, const char *uri)
void search_activate(GtkEntry* self, GtkNotebook* notebook)
{
gtk_notebook_set_show_border(notebook, false);
gtk_notebook_set_show_tabs(notebook, false);
notebook_append(notebook, uri);
if (entry_mode == _SEARCH)
load_uri(notebook_get_webview(notebook),
gtk_entry_buffer_get_text(search_buf));
else if (entry_mode == _FIND)
webkit_find_controller_search(
webkit_web_view_get_find_controller(notebook_get_webview(notebook)),
gtk_entry_buffer_get_text(search_buf),
WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | WEBKIT_FIND_OPTIONS_WRAP_AROUND,
G_MAXUINT);
gtk_widget_hide(GTK_WIDGET(bar));
}
void setup(GtkNotebook *notebook, const char *uri)
void window_init(GtkNotebook* notebook)
{
window = GTK_WINDOW(gtk_window_new(0));
notebook = GTK_NOTEBOOK(gtk_notebook_new());
bar = GTK_HEADER_BAR(gtk_header_bar_new());
search_buf = GTK_ENTRY_BUFFER(gtk_entry_buffer_new("", 0));
search = GTK_ENTRY(gtk_entry_new_with_buffer(search_buf));
window_init(notebook);
notebook_init(notebook, uri);
g_object_set(gtk_settings_get_default(), GTK, NULL);
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(notebook));
gtk_widget_show_all(GTK_WIDGET(window));
gtk_widget_hide(GTK_WIDGET(bar));
GtkCssProvider* css = gtk_css_provider_new();
gtk_css_provider_load_from_path(css, "/usr/share/themes/rose/style.css",
NULL);
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
GTK_STYLE_PROVIDER(css), 800);
gtk_entry_buffer_new("", 0);
gtk_entry_set_alignment(search, 0.48);
gtk_widget_set_size_request(GTK_WIDGET(search), 1200, -1);
gtk_header_bar_set_custom_title(bar, GTK_WIDGET(search));
gtk_window_set_titlebar(window, GTK_WIDGET(bar));
g_signal_connect(search, "activate", G_CALLBACK(search_activate), notebook);
g_signal_connect(window, "key-press-event", G_CALLBACK(keypress), notebook);
g_signal_connect(window, "destroy", G_CALLBACK(exit), notebook);
}
int main(int argc, char **argv)
void notebook_init(GtkNotebook* notebook, const char* uri)
{
GtkNotebook *notebook;
gtk_init(NULL, NULL);
setup(notebook, argc > 1 ? argv[1] : NULL);
gtk_main();
gtk_notebook_set_show_border(notebook, false);
gtk_notebook_set_show_tabs(notebook, false);
notebook_append(notebook, uri);
}
void setup(GtkNotebook* notebook, int argc, char** argv)
{
// Define GTK entities
window = GTK_WINDOW(gtk_window_new(0));
notebook = GTK_NOTEBOOK(gtk_notebook_new());
bar = GTK_HEADER_BAR(gtk_header_bar_new());
search_buf = GTK_ENTRY_BUFFER(gtk_entry_buffer_new("", 0));
search = GTK_ENTRY(gtk_entry_new_with_buffer(search_buf));
gtk_window_set_default_size(window, WIDTH, HEIGHT);
window_init(notebook);
// Initialize with first uri
char* first_uri = argc > 1 ? argv[1] : NULL;
notebook_init(notebook, first_uri);
g_object_set(gtk_settings_get_default(), GTK, NULL);
// More GTK stuff
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(notebook));
gtk_widget_show_all(GTK_WIDGET(window));
gtk_widget_hide(GTK_WIDGET(bar));
// Deal with more uris, if this is necessary.
if (argc > 2) {
gtk_notebook_set_show_tabs(notebook, true);
for (int i = 2; i < argc; i++) {
notebook_append(notebook, argv[i]);
}
}
}
int main(int argc, char** argv)
{
GtkNotebook* notebook;
gtk_init(NULL, NULL);
setup(notebook, argc, argv);
gtk_main();
// this point is never reached, since gtk_main(); never exits.
}

BIN
screenshots/1-startup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

BIN
screenshots/2-blog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

View File

@ -10,7 +10,10 @@
margin: 0px;
outline-color: @Lavender;
color: @Text;
border-bottom-color: @Base;
border-color: white;
font-size: 16px;
/*@Base; */
/* border-bottom-color: @Base; */
}
window, notebook, headerbar {
@ -20,11 +23,21 @@ window, notebook, headerbar {
tabs {
background-color: @Base;
padding: 3px;
outline-color: white;
border-color: @Base;
}
tab {
background-color: @Base;
margin: 2px 5px 2px 0px;
padding: 5px;
border-style: solid;
/*border-color: white;
border-bottom-color: white;
outline-color: white;
margin: 5px;
padding-left: 10px;
padding-right: 10px; */
}
entry {
@ -33,5 +46,7 @@ entry {
}
entry:focus {
box-shadow: none;
background-color: @Surface0;
padding-left: 10px;
}

View File

@ -0,0 +1,5 @@
DEPS='webkit2gtk-4.0'
INCS=`pkg-config --cflags ${DEPS}`
LIBS=`pkg-config --libs ${DEPS}`
echo $INCS
echo $LIBS

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

View File

@ -0,0 +1,52 @@
@define-color Surface0 #313244;
@define-color Surface1 #45475a;
@define-color Base #1e1e2e;
@define-color Mantle #181825;
@define-color Lavender #b4befe;
@define-color Text #cdd6f4;
* {
padding: 0px;
margin: 0px;
outline-color: @Lavender;
color: @Text;
border-color: white;
font-size: 16px;
/*@Base; */
/* border-bottom-color: @Base; */
}
window, notebook, headerbar {
background: @Base;
}
tabs {
background-color: @Base;
padding: 3px;
outline-color: white;
border-color: @Base;
}
tab {
background-color: @Base;
margin: 2px 5px 2px 0px;
padding: 5px;
border-style: solid;
/*border-color: white;
border-bottom-color: white;
outline-color: white;
margin: 5px;
padding-left: 10px;
padding-right: 10px; */
}
entry {
background-color: @Surface0;
padding-left: 10px;
}
entry:focus {
background-color: @Surface0;
padding-left: 10px;
}

View File

@ -0,0 +1,37 @@
@define-color Surface0 #313244;
@define-color Surface1 #45475a;
@define-color Base #1e1e2e;
@define-color Mantle #181825;
@define-color Lavender #b4befe;
@define-color Text #cdd6f4;
* {
padding: 0px;
margin: 0px;
outline-color: @Lavender;
color: @Text;
border-bottom-color: @Base;
}
window, notebook, headerbar {
background: @Base;
}
tabs {
background-color: @Base;
padding: 3px;
}
tab {
background-color: @Base;
margin: 5px;
}
entry {
background-color: @Surface0;
padding-left: 10px;
}
entry:focus {
box-shadow: none;
}

View File

@ -0,0 +1,31 @@
# Dependencies
sudo apt install libwebkit2gtk-4.0-dev
sudo apt install clang
# sudo apt instal sudo apt install gstreamer1.0-plugins-good gstreamer1.0-libav
# Adblock
git clone https://github.com/jun7/wyebadblock
cd wyebadblock
make
sudo make install
cd ..
mkdir -p ~/.config/wyebadblock
cd ~/.config/wyebadblock
wget https://easylist.to/easylist/easylist.txt
cd -
# Rose config
user=$(whoami)
mkdir -p /home/$user/.cache/rose
cp ../../config.def.h ../../config.h # you should also probably customize this yourself.
sed "s/fenze/$user/g" ../../config.h
# sudo bash ../../install.sh
cd ../..
make build # or just make
sudo make install
cd -
# Ubuntu desktop icon
chmod +x rose.desktop
sudo cp rose.desktop /usr/share/applications

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

View File

@ -0,0 +1 @@
<https://www.onlygfx.com/red-rose-png-image-transparent/>

View File

@ -0,0 +1,9 @@
#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec= /usr/bin/rose %u
Name=Rose
Comment=Minimalistic browser
Icon=/home/loki/Documents/core/software/fresh/C/rose-browser/rosenrot/user-scripts/ubuntu-20.04/rose-images/rose-desktop-icon.png

View File

@ -0,0 +1,9 @@
In case you arrive at a segmentation fault when working on rose, you can use valgrind.
To do this, you can compile rose with the `DEBUG` value in `build.sh` set to `-g`
and then:
```
valgrind --track-origins=yes ./rose
```