diff --git a/rosenrot4_beta.c b/rosenrot4_beta.c index b31f9ec..1273bd4 100644 --- a/rosenrot4_beta.c +++ b/rosenrot4_beta.c @@ -32,7 +32,8 @@ static int custom_style_enabled = 1; /* Forward declarations */ void toggle_bar(GtkNotebook* notebook, Bar_entry_mode mode); void notebook_create_new_tab(GtkNotebook* notebook, const char* uri); - +static int handle_signal_keypress(void *self, int keyval, int keycode, + GdkModifierType state, void *controller); /* Utils */ WebKitWebView* notebook_get_webview(GtkNotebook* notebook) @@ -63,7 +64,7 @@ void load_uri(WebKitWebView* view, const char* uri) char uri_expanded[l]; str_init(uri_expanded, l); int check = shortcut_expand(uri, uri_expanded); - if (check == 2) { + if (check == 2) { /* Should use an enum here */ webkit_web_view_load_uri(view, uri_expanded); } else { // Feed into search engine. @@ -80,55 +81,12 @@ void set_custom_style(WebKitWebView* view) if (custom_style_enabled) { char* style_js = malloc(STYLE_N + 1); read_style_js(style_js); - webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); + // webkit_web_view_evaluate_javascript(view, style_js, -1, NULL, "rosenrot-style-plugin", NULL, NULL, NULL); free(style_js); } } -/* Handle shortcuts */ -int handle_shortcut(func id) -{ - - WebKitWebView* view = notebook_get_webview(notebook); - NOTNULL(notebook); - NOTNULL(view); - - switch (id) { - case show_searchbar: - toggle_bar(notebook, _SEARCH); - break; - case hide_bar: - toggle_bar(notebook, _HIDDEN); - break; - } - - return 1; -} - -/* Listen to keypresses */ - -static int handle_signal_keypress(void *self, int keyval, int keycode, - GdkModifierType state, void *controller) -{ - // (void) self, (void) keycode, (void) controller; - - // fprintf(stdout, "New keypress!\n"); - printf("New keypress\n"); - - if (1) { - printf("Keypress state: %d\n", state); - printf("Keypress value: %d\n", keyval); - } - for (int i = 0; i < sizeof(shortcut) / sizeof(shortcut[0]); i++){ - if ((state & shortcut[i].mod || shortcut[i].mod == 0x0) && keyval == shortcut[i].key) { - return handle_shortcut(shortcut[i].id); - } - } - - return 0; - -} - +/* New tabs */ WebKitWebView* create_new_webview() { @@ -140,6 +98,38 @@ WebKitWebView* create_new_webview() return view; } +WebKitWebView* create_new_webview_full() +{ + char* style; + WebKitSettings* settings; + WebKitCookieManager* cookiemanager; + WebKitNetworkSession* network_session; + WebKitUserContentManager* contentmanager; + + settings = webkit_settings_new_with_settings(WEBKIT_DEFAULT_SETTINGS, 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/120.0.0.0 Safari/537.3"); + // https://www.useragents.me + } + network_session = webkit_network_session_new(DATA_DIR, DATA_DIR); + contentmanager = webkit_user_content_manager_new(); + cookiemanager = webkit_network_session_get_cookie_manager(network_session); + + webkit_cookie_manager_set_persistent_storage(cookiemanager, DATA_DIR "/cookies.sqlite", WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE); + + webkit_cookie_manager_set_accept_policy(cookiemanager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + + if (g_file_get_contents("/opt/rosenrot/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, "network-session", network_session, "user-content-manager", contentmanager, NULL); +} + GtkWidget* handle_signal_create_new_tab(WebKitWebView* self, WebKitNavigationAction* navigation_action, GtkNotebook* notebook) @@ -156,17 +146,10 @@ GtkWidget* handle_signal_create_new_tab(WebKitWebView* self, webkit_web_view_evaluate_javascript(self, "alert('Too many tabs, not opening a new one')", -1, NULL, "rosenrot-alert-numtabs", NULL, NULL, NULL); } return GTK_WIDGET(self); // 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_create_new_tab - or duplicating its contents, for unclear gain. - */ } -void notebook_create_new_tab(GtkNotebook* notebook, const char* uri) +void notebook_create_new_tab_mini(GtkNotebook* notebook, const char* uri) { WebKitWebView* view = create_new_webview(); @@ -180,6 +163,51 @@ void notebook_create_new_tab(GtkNotebook* notebook, const char* uri) gtk_notebook_set_tab_label_text(notebook, GTK_WIDGET(view), "-"); } +void notebook_create_new_tab(GtkNotebook* notebook, const char* uri) +{ + NOTNULL(notebook); + if (num_tabs < MAX_NUM_TABS || MAX_NUM_TABS == 0) { + WebKitWebView* view = create_new_webview(); + NOTNULL(view); + + // g_signal_connect(view, "load_changed", G_CALLBACK(handle_signal_load_changed), notebook); + // I suspect there is something wonky going on here + // YEP, there is a problem here + // todo: fix + /* GtkEventController* event_controller_load_changed; + event_controller_load_changed = gtk_event_controller_key_new(); + g_signal_connect_object(event_controller_load_changed, "load_changed", G_CALLBACK(handle_signal_load_changed), notebook, G_CONNECT_DEFAULT); + gtk_widget_add_controller(GTK_WIDGET(view), event_controller_load_changed); + */ + + g_signal_connect(view, "create", G_CALLBACK(handle_signal_create_new_tab), notebook); + // I suspect there is something wonky going on here + /* + GtkEventController* event_controller_create_new_tab; + event_controller_create_new_tab = gtk_event_controller_key_new(); + g_signal_connect_object(event_controller_create_new_tab, "create", G_CALLBACK(handle_signal_create_new_tab), notebook, G_CONNECT_DEFAULT); + gtk_widget_add_controller(GTK_WIDGET(view), event_controller_create_new_tab); + */ + + int n = gtk_notebook_append_page(notebook, GTK_WIDGET(view), NULL); + gtk_notebook_set_tab_reorderable(notebook, GTK_WIDGET(view), true); + NOTNULL(window); + NOTNULL(bar.widget); + gtk_widget_set_visible(GTK_WIDGET(window), 1); + gtk_widget_set_visible(GTK_WIDGET(bar.widget), 0); + load_uri(view, (uri) ? uri : HOME); + + set_custom_style(view); + + 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_START_LEVEL); + num_tabs += 1; + } else { + // To do: show js message + } +} + /* Top bar */ void toggle_bar(GtkNotebook* notebook, Bar_entry_mode mode) { @@ -230,6 +258,174 @@ void handle_signal_bar_press_enter(void* data) gtk_widget_hide(GTK_WIDGET(bar.widget)); } + + +/* Handle shortcuts */ +int handle_shortcut_mini(func id) +{ + + WebKitWebView* view = notebook_get_webview(notebook); + NOTNULL(notebook); + NOTNULL(view); + + switch (id) { + case show_searchbar: + toggle_bar(notebook, _SEARCH); + break; + case hide_bar: + toggle_bar(notebook, _HIDDEN); + break; + } + + return 1; +} + +int handle_shortcut(func id) +{ + static double zoom = ZOOM_START_LEVEL; + static bool is_fullscreen = 0; + + WebKitWebView* view = notebook_get_webview(notebook); + NOTNULL(notebook); + NOTNULL(view); + + switch (id) { + case goback: + webkit_web_view_go_back(view); + break; + case goforward: + webkit_web_view_go_forward(view); + break; + + case toggle_custom_style: /* Ctrl s + Ctrl Shift R to reload */ + if (custom_style_enabled) + custom_style_enabled = 0; + else + custom_style_enabled = 1; + // break; passthrough + case refresh: + webkit_web_view_reload(view); + break; + case refresh_force: + webkit_web_view_reload_bypass_cache(view); + break; + + case back_to_home: + load_uri(view, HOME); + break; + + case zoomin: + webkit_web_view_set_zoom_level(view, + (zoom += ZOOM_STEPSIZE)); + break; + case zoomout: + webkit_web_view_set_zoom_level(view, + (zoom -= ZOOM_STEPSIZE)); + break; + case zoom_reset: + webkit_web_view_set_zoom_level(view, + (zoom = ZOOM_START_LEVEL)); + break; + + case prev_tab:; // declarations aren't statements + // https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement + int n = gtk_notebook_get_n_pages(notebook); + int k = gtk_notebook_get_current_page(notebook); + int l = (n + k - 1) % n; + gtk_notebook_set_current_page(notebook, l); + break; + case next_tab:; + int m = gtk_notebook_get_n_pages(notebook); + int i = gtk_notebook_get_current_page(notebook); + int j = (i + 1) % m; + gtk_notebook_set_current_page(notebook, j); + break; + case close_tab: + gtk_notebook_remove_page(notebook, gtk_notebook_get_current_page(notebook)); + num_tabs -= 1; + + 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: + toggle_bar(notebook, _SEARCH); + break; + case show_finder: + toggle_bar(notebook, _FIND); + break; + + case finder_next: + webkit_find_controller_search_next(webkit_web_view_get_find_controller(view)); + break; + case finder_prev: + webkit_find_controller_search_previous(webkit_web_view_get_find_controller(view)); + break; + + case new_tab: + notebook_create_new_tab(notebook, NULL); + gtk_notebook_set_show_tabs(notebook, true); + toggle_bar(notebook, _SEARCH); + break; + + case hide_bar: + gtk_widget_set_visible(GTK_WIDGET(bar.widget), 0); + toggle_bar(notebook, _HIDDEN); + break; + + case prettify: { + if (READABILITY_ENABLED) { + char* readability_js = malloc(READABILITY_N + 1); + read_readability_js(readability_js); + webkit_web_view_evaluate_javascript(view, readability_js, -1, NULL, "rosenrot-readability-plugin", NULL, NULL, NULL); + free(readability_js); + } + break; + } + } + + return 1; +} + + +/* Listen to keypresses */ + +static int handle_signal_keypress(void *self, int keyval, int keycode, + GdkModifierType state, void *controller) +{ + // (void) self, (void) keycode, (void) controller; + + // fprintf(stdout, "New keypress!\n"); + printf("New keypress\n"); + + if (1) { + printf("Keypress state: %d\n", state); + printf("Keypress value: %d\n", keyval); + } + for (int i = 0; i < sizeof(shortcut) / sizeof(shortcut[0]); i++){ + if ((state & shortcut[i].mod || shortcut[i].mod == 0x0) && keyval == shortcut[i].key) { + printf("New shortcut, with id: %d\n", shortcut[i].id); + return handle_shortcut(shortcut[i].id); + } + } + + return 0; + +} + int main(int argc, char** argv) { /* Initialize GTK in general */ @@ -274,10 +470,19 @@ int main(int argc, char** argv) /* Show to user */ gtk_widget_set_visible(GTK_WIDGET(window), 1); + if (argc != 0) gtk_widget_set_visible(GTK_WIDGET(bar.widget), 0); + + /* Deal with more tabs */ + if (argc > 2) { + gtk_notebook_set_show_tabs(notebook, true); + for (int i = 2; i < argc; i++) { + notebook_create_new_tab(notebook, argv[i]); + } + } // Enter the main event loop, and wait for user interaction printf("\nEntering main loop"); - while (g_list_model_get_n_items(gtk_window_get_toplevels()) > 0) + while (g_list_model_get_n_items(gtk_window_get_toplevels()) > 0 && num_tabs > 0) g_main_context_iteration(NULL, TRUE); return 0;