Compare commits

..

6 Commits

53 changed files with 441 additions and 3611 deletions

37
.clang-format Normal file
View File

@ -0,0 +1,37 @@
# 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 +1,3 @@
rose
config.h
.clang-format

View File

@ -1,73 +1,21 @@
## Rosenrot
<h3 align=center> Rose Browser</h1>
<h4 align=center>Minimal browser based on webkit2gtk</h4>
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.
#### 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
#
### 👐 Contribute
See [contributing.md](https://github.com/mini-rose/rose/.github/contributing.md).
- 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.
### 📜 License
Rose is released under own license, which grants the following permissions:
- Commercial use
- Distribution
- Modification
- Private use

11
build.sh Executable file
View File

@ -0,0 +1,11 @@
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

79
config.def.h Normal file
View File

@ -0,0 +1,79 @@
/*
* 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"
#define WIDTH 500
#define HEIGHT 400
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 }
};

View File

@ -1,99 +0,0 @@
#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 }
};
*/

6
install.sh Executable file
View File

@ -0,0 +1,6 @@
./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
View File

@ -1,21 +0,0 @@
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.

View File

@ -1,66 +0,0 @@
# 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

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

View File

@ -1,84 +0,0 @@
#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

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

View File

@ -1,65 +0,0 @@
#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

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

View File

@ -1,11 +0,0 @@
#!/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

@ -1,19 +0,0 @@
#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

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

Binary file not shown.

View File

@ -1,30 +0,0 @@
#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

@ -1,8 +0,0 @@
#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

@ -1,8 +0,0 @@
#!/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

@ -1,27 +0,0 @@
/* 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

@ -1,23 +0,0 @@
/* 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);

View File

@ -1,5 +0,0 @@
## 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

@ -1,8 +0,0 @@
#!/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"

View File

@ -1,30 +0,0 @@
#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);
}
*/

View File

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

View File

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

657
rose.c
View File

@ -1,463 +1,320 @@
#include <stdbool.h>
#include <stdlib.h> // necessary for free, malloc.
#include <string.h>
#include <webkit2/webkit2.h>
/*
* 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 "config.h"
#include "plugins/libre_redirect/libre_redirect.h"
#include "plugins/readability/readability.h"
#include "plugins/style/style.h"
#include <webkit2/webkit2.h>
// #include "plugins/stand_in/stand_in.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
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 };
enum { _SEARCH, _FIND };
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);
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);
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);
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);
}
WebKitWebView* notebook_get_webview(GtkNotebook* notebook)
void load_uri(WebKitWebView *view, const char *uri)
{
return WEBKIT_WEB_VIEW(gtk_notebook_get_nth_page(
notebook, gtk_notebook_get_current_page(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);
}
}
void load_uri(WebKitWebView* view, const char* uri)
void load_changed(WebKitWebView *self, WebKitLoadEvent load_event, 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 {
// 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);
}
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));
}
}
void redirect_if_annoying(WebKitWebView* view, const char* uri)
void notebook_append(GtkNotebook *notebook, const char *uri)
{
int l = LIBRE_N + strlen(uri) + 1;
char uri_filtered[l];
str_init(uri_filtered, l);
GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(window));
GdkVisual *rgba_visual = gdk_screen_get_rgba_visual(screen);
GdkRGBA rgba;
int check = libre_redirect(uri, uri_filtered);
gdk_rgba_parse(&rgba, BG_COLOR);
if (check == 2) {
webkit_web_view_load_uri(view, 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);
}
void load_changed(WebKitWebView* self, WebKitLoadEvent load_event,
GtkNotebook* notebook)
WebKitWebView *notebook_get_webview(GtkNotebook *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));
}
}
return WEBKIT_WEB_VIEW(
gtk_notebook_get_nth_page(notebook, gtk_notebook_get_current_page(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.
*/
GtkWidget* handle_create_new_tab(WebKitWebView* self,
WebKitNavigationAction* navigation_action,
GtkNotebook* notebook)
void show_bar(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.
*/
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)));
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));
}
}
void notebook_append(GtkNotebook* notebook, const char* uri)
int handle_key(func id, GtkNotebook *notebook)
{
GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(window));
GdkVisual* rgba_visual = gdk_screen_get_rgba_visual(screen);
GdkRGBA rgba;
static double zoom = ZOOM;
static bool is_fullscreen = 0;
gdk_rgba_parse(&rgba, BG_COLOR);
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;
WebKitWebView* view = webview_new();
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;
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 back_to_home:
load_uri(notebook_get_webview(notebook), HOME);
break;
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);
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;
}
void show_bar(GtkNotebook* notebook)
int keypress(void *self, GdkEvent *e, 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 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)));
(void) self;
if (search_text != NULL)
gtk_entry_buffer_set_text(search_buf, search_text, strlen(search_text));
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_set_placeholder_text(search, "Find");
gtk_widget_show(GTK_WIDGET(bar));
gtk_window_set_focus(window, GTK_WIDGET(search));
}
return 0;
}
int handle_key(func id, GtkNotebook* notebook)
void search_activate(GtkEntry *self, GtkNotebook *notebook)
{
static double zoom = ZOOM;
static bool is_fullscreen = 0;
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);
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;
gtk_widget_hide(GTK_WIDGET(bar));
}
int keypress(void* self, GdkEvent* e, GtkNotebook* notebook)
void window_init(GtkNotebook *notebook)
{
(void)self;
GtkCssProvider *css = gtk_css_provider_new();
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_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);
return 0;
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);
}
void search_activate(GtkEntry* self, GtkNotebook* notebook)
void notebook_init(GtkNotebook *notebook, const char *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));
gtk_notebook_set_show_border(notebook, false);
gtk_notebook_set_show_tabs(notebook, false);
notebook_append(notebook, uri);
}
void window_init(GtkNotebook* notebook)
void setup(GtkNotebook *notebook, const char *uri)
{
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);
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_fullscreen(window);
gtk_window_set_default_size(window, WIDTH, HEIGHT);
// gtk_window_set_resizable (window, FALSE);
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));
webkit_web_view_set_zoom_level(notebook_get_webview(notebook), ZOOM);
}
void notebook_init(GtkNotebook* notebook, const char* uri)
int main(int argc, char **argv)
{
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.
GtkNotebook *notebook;
gtk_init(NULL, NULL);
setup(notebook, argc > 1 ? argv[1] : NULL);
gtk_main();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

View File

@ -10,10 +10,7 @@
margin: 0px;
outline-color: @Lavender;
color: @Text;
border-color: white;
font-size: 16px;
/*@Base; */
/* border-bottom-color: @Base; */
border-bottom-color: @Base;
}
window, notebook, headerbar {
@ -23,21 +20,11 @@ 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 {
@ -46,7 +33,5 @@ entry {
}
entry:focus {
background-color: @Surface0;
padding-left: 10px;
box-shadow: none;
}

9
ubuntu-stuff/rose.desktop Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec= /usr/bin/rose "https://duckduckgo.com"
Name=Rose
Comment=Minimalistic browser
Icon=/home/loki/Documents/core/software/fresh/linux/rose/ubuntu-stuff/rose.png

View File

Before

Width:  |  Height:  |  Size: 625 KiB

After

Width:  |  Height:  |  Size: 625 KiB

View File

@ -0,0 +1,17 @@
sudo apt install libwebkit2gtk-4.0-dev
sudo apt install clang
# sudo apt instal sudo apt install gstreamer1.0-plugins-good gstreamer1.0-libav
git clone https://github.com/jun7/wyebadblock
cd wyebadblock
make
sudo make install
user="loki"
cp config.def.h config.h
sed "s/fenze/$user/g" config.h
./install.sh
chmod +x ./ubuntu-stuff/rose.desktop
cp ./ubuntu-stuff/rose.desktop /usr/share/applications

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

View File

@ -1,52 +0,0 @@
@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

@ -1,37 +0,0 @@
@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

@ -1,31 +0,0 @@
# 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.

Before

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

View File

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

View File

@ -1,9 +0,0 @@
#!/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

@ -1,9 +0,0 @@
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
```