2024-07-21 14:44:45 +00:00
# include <gdk/gdk.h>
2024-02-11 17:25:46 +00:00
# include <stdlib.h>
# include <string.h>
2024-07-20 22:08:26 +00:00
2024-07-21 00:35:15 +00:00
# include "config.h"
2024-03-14 18:16:47 +00:00
# include "plugins/plugins.h"
2024-07-21 14:44:45 +00:00
/* Global variables */
2024-02-11 12:52:38 +00:00
static GtkNotebook * notebook ;
2024-07-21 14:44:45 +00:00
static GtkWindow * window ;
2024-07-22 23:04:39 +00:00
typedef enum { _SEARCH , _FIND , _HIDDEN } Bar_entry_mode ;
2024-02-11 15:15:18 +00:00
static struct {
2024-02-11 17:25:46 +00:00
GtkHeaderBar * widget ;
GtkEntry * line ;
GtkEntryBuffer * line_text ;
2024-03-24 11:07:29 +00:00
Bar_entry_mode entry_mode ;
2024-03-14 17:59:27 +00:00
} bar ;
2024-02-11 15:15:18 +00:00
static int num_tabs = 0 ;
2024-04-14 12:53:45 +00:00
static int custom_style_enabled = 1 ;
2023-02-05 02:57:29 +00:00
2024-03-24 11:45:21 +00:00
/* Forward declarations */
2024-03-24 11:07:29 +00:00
void toggle_bar ( GtkNotebook * notebook , Bar_entry_mode mode ) ;
2024-03-23 21:10:59 +00:00
void notebook_create_new_tab ( GtkNotebook * notebook , const char * uri ) ;
2024-07-21 14:44:45 +00:00
static int handle_signal_keypress ( void * self , int keyval , int keycode ,
GdkModifierType state , void * controller ) ;
2024-03-23 21:10:59 +00:00
2024-02-11 17:04:22 +00:00
/* Utils */
2024-07-21 14:44:45 +00:00
WebKitWebView * notebook_get_webview ( GtkNotebook * notebook ) /* TODO: Think through whether to pass global variables or not */
2024-02-11 17:04:22 +00:00
{
2024-07-21 14:44:45 +00:00
WebKitWebView * view = WEBKIT_WEB_VIEW ( gtk_notebook_get_nth_page ( notebook , gtk_notebook_get_current_page ( notebook ) ) ) ;
NULLCHECK ( view ) ;
return view ;
2024-02-11 17:04:22 +00:00
}
2024-07-21 14:44:45 +00:00
/* Load content */
2023-03-28 16:14:13 +00:00
void load_uri ( WebKitWebView * view , const char * uri )
{
2024-07-21 14:44:45 +00:00
bool is_empty_uri = ( strlen ( uri ) = = 0 ) ;
if ( is_empty_uri ) {
2024-03-14 19:31:07 +00:00
webkit_web_view_load_uri ( view , " " ) ;
2024-03-24 11:07:29 +00:00
toggle_bar ( notebook , _SEARCH ) ;
2024-07-23 01:54:36 +00:00
return
}
bool has_direct_uri_prefix = g_str_has_prefix ( uri , " http:// " ) | | g_str_has_prefix ( uri , " https:// " ) | | g_str_has_prefix ( uri , " file:// " ) | | g_str_has_prefix ( uri , " about: " ) ;
if ( has_direct_uri_prefix ) {
2023-03-28 16:14:13 +00:00
webkit_web_view_load_uri ( view , uri ) ;
2024-07-23 01:54:36 +00:00
return ;
}
bool has_common_domain_extension = ( strstr ( uri , " .com " ) | | strstr ( uri , " .org " ) ) ;
if ( has_common_domain_extension ) {
2024-03-29 18:13:32 +00:00
char tmp [ strlen ( " https:// " ) + strlen ( uri ) + 1 ] ;
snprintf ( tmp , sizeof ( tmp ) + 1 , " https://%s " , uri ) ;
2024-03-23 19:18:00 +00:00
webkit_web_view_load_uri ( view , tmp ) ;
2024-07-23 01:54:36 +00:00
return
}
int l = SHORTCUT_N + strlen ( uri ) + 1 ;
char uri_expanded [ l ] ;
str_init ( uri_expanded , l ) ;
int check = shortcut_expand ( uri , uri_expanded ) ;
bool has_shortcut = ( check = = 2 ) ;
if ( has_shortcut ) {
2024-07-21 14:44:45 +00:00
webkit_web_view_load_uri ( view , uri_expanded ) ;
2024-07-23 01:54:36 +00:00
return
}
char tmp [ strlen ( uri ) + strlen ( SEARCH ) ] ;
snprintf ( tmp , sizeof ( tmp ) , SEARCH , uri ) ;
webkit_web_view_load_uri ( view , tmp ) ;
2023-03-28 16:14:13 +00:00
}
2022-12-17 19:54:27 +00:00
2024-02-11 16:26:20 +00:00
/* Deal with new load or changed load */
2023-03-28 16:14:13 +00:00
void redirect_if_annoying ( WebKitWebView * view , const char * uri )
{
2024-02-11 17:04:22 +00:00
if ( LIBRE_REDIRECT_ENABLED ) {
int l = LIBRE_N + strlen ( uri ) + 1 ;
char uri_filtered [ l ] ;
str_init ( uri_filtered , l ) ;
2022-12-18 16:42:50 +00:00
2024-02-11 17:04:22 +00:00
int check = libre_redirect ( uri , uri_filtered ) ;
2024-03-23 20:48:42 +00:00
if ( check = = 2 ) webkit_web_view_load_uri ( view , uri_filtered ) ;
2024-02-11 17:04:22 +00:00
}
}
2024-02-11 17:25:46 +00:00
void set_custom_style ( WebKitWebView * view )
{
2024-04-14 12:53:45 +00:00
if ( custom_style_enabled ) {
2024-02-11 17:04:22 +00:00
char * style_js = malloc ( STYLE_N + 1 ) ;
read_style_js ( style_js ) ;
2024-07-21 15:29:08 +00:00
webkit_web_view_evaluate_javascript ( view , style_js , - 1 , NULL , " rosenrot-style-plugin " , NULL , NULL , NULL ) ;
2024-02-11 17:04:22 +00:00
free ( style_js ) ;
2023-03-28 16:14:13 +00:00
}
2022-12-17 19:54:27 +00:00
}
2024-07-21 14:44:45 +00:00
2024-02-11 15:57:06 +00:00
void handle_signal_load_changed ( WebKitWebView * self , WebKitLoadEvent load_event ,
2023-03-28 16:14:13 +00:00
GtkNotebook * notebook )
2022-11-14 20:41:43 +00:00
{
2023-03-28 16:14:13 +00:00
switch ( load_event ) {
2024-03-24 11:45:21 +00:00
// https://webkitgtk.org/reference/webkit2gtk/2.5.1/WebKitWebView.html
2024-03-23 20:48:42 +00:00
case WEBKIT_LOAD_STARTED :
case WEBKIT_LOAD_COMMITTED :
set_custom_style ( self ) ;
case WEBKIT_LOAD_REDIRECTED :
redirect_if_annoying ( self , webkit_web_view_get_uri ( self ) ) ;
break ;
case WEBKIT_LOAD_FINISHED : {
2024-07-20 21:25:54 +00:00
set_custom_style ( self ) ;
2024-03-23 20:48:42 +00:00
/* 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 ;
}
2022-12-17 19:54:27 +00:00
}
2024-03-23 20:48:42 +00:00
tab_title [ max_length ] = ' \0 ' ;
2023-03-28 16:14:13 +00:00
}
2024-03-23 20:48:42 +00:00
gtk_notebook_set_tab_label_text ( notebook , GTK_WIDGET ( self ) ,
webpage_title = = NULL ? " — " : tab_title ) ;
}
2023-03-28 16:14:13 +00:00
}
2022-11-14 20:41:43 +00:00
}
2024-07-21 14:44:45 +00:00
/* New tabs */
WebKitWebView * create_new_webview ( )
{
WebKitSettings * 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
}
WebKitNetworkSession * network_session = webkit_network_session_new ( DATA_DIR , DATA_DIR ) ;
WebKitUserContentManager * contentmanager = webkit_user_content_manager_new ( ) ;
WebKitCookieManager * 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 ) ;
WebKitWebView * view = g_object_new ( WEBKIT_TYPE_WEB_VIEW , " settings " , settings , " network-session " , network_session , " user-content-manager " , contentmanager , NULL ) ;
NULLCHECK ( view ) ;
GtkEventController * event_controller = gtk_event_controller_key_new ( ) ;
g_signal_connect ( event_controller , " key-pressed " , G_CALLBACK ( handle_signal_keypress ) , NULL ) ;
gtk_widget_add_controller ( GTK_WIDGET ( view ) , event_controller ) ;
return view ;
}
2024-02-11 15:57:06 +00:00
GtkWidget * handle_signal_create_new_tab ( WebKitWebView * self ,
2023-03-28 16:14:13 +00:00
WebKitNavigationAction * navigation_action ,
GtkNotebook * notebook )
2023-06-17 06:29:27 +00:00
{
2024-07-21 14:44:45 +00:00
NULLCHECK ( self ) ;
NULLCHECK ( notebook ) ;
2024-02-11 15:15:18 +00:00
if ( num_tabs < MAX_NUM_TABS | | num_tabs = = 0 ) {
2023-06-17 06:29:27 +00:00
WebKitURIRequest * uri_request = webkit_navigation_action_get_request ( navigation_action ) ;
const char * uri = webkit_uri_request_get_uri ( uri_request ) ;
2024-07-21 18:54:32 +00:00
webkit_web_view_stop_loading ( self ) ;
2023-06-17 06:29:27 +00:00
printf ( " Creating new window: %s \n " , uri ) ;
2024-02-11 16:15:24 +00:00
notebook_create_new_tab ( notebook , uri ) ;
2023-06-17 06:29:27 +00:00
gtk_notebook_set_show_tabs ( notebook , true ) ;
} else {
2024-03-12 16:53:45 +00:00
webkit_web_view_evaluate_javascript ( self , " alert('Too many tabs, not opening a new one') " , - 1 , NULL , " rosenrot-alert-numtabs " , NULL , NULL , NULL ) ;
2023-06-17 06:29:27 +00:00
}
2024-07-22 23:04:39 +00:00
return ABORT_REQUEST_ON_CURRENT_TAB ;
// Could also return GTK_WIDGET(self), in which case the new uri would also be loaded in the current webview. This could be interesting if I wanted to e.g., open an alternative frontend in a new tab
2023-02-05 01:31:57 +00:00
}
2024-02-11 17:23:04 +00:00
2024-02-11 16:15:24 +00:00
void notebook_create_new_tab ( GtkNotebook * notebook , const char * uri )
2022-11-14 20:41:43 +00:00
{
2024-02-11 17:23:04 +00:00
if ( num_tabs < MAX_NUM_TABS | | MAX_NUM_TABS = = 0 ) {
WebKitWebView * view = create_new_webview ( ) ;
2024-07-21 14:44:45 +00:00
NULLCHECK ( view ) ;
2023-06-17 06:29:27 +00:00
2024-07-21 14:44:45 +00:00
g_signal_connect ( view , " load_changed " , G_CALLBACK ( handle_signal_load_changed ) , notebook ) ;
g_signal_connect ( view , " create " , G_CALLBACK ( handle_signal_create_new_tab ) , notebook ) ;
2023-06-17 06:29:27 +00:00
2024-02-11 16:26:20 +00:00
int n = gtk_notebook_append_page ( notebook , GTK_WIDGET ( view ) , NULL ) ;
2023-06-17 06:29:27 +00:00
gtk_notebook_set_tab_reorderable ( notebook , GTK_WIDGET ( view ) , true ) ;
2024-07-21 14:44:45 +00:00
NULLCHECK ( window ) ;
NULLCHECK ( bar . widget ) ;
2024-07-20 22:52:32 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( window ) , 1 ) ;
gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 0 ) ;
2023-06-17 06:29:27 +00:00
load_uri ( view , ( uri ) ? uri : HOME ) ;
2024-02-11 17:23:04 +00:00
set_custom_style ( view ) ;
2023-06-17 06:29:27 +00:00
gtk_notebook_set_current_page ( notebook , n ) ;
gtk_notebook_set_tab_label_text ( notebook , GTK_WIDGET ( view ) , " - " ) ;
2024-03-24 11:45:21 +00:00
webkit_web_view_set_zoom_level ( view , ZOOM_START_LEVEL ) ;
2024-02-11 15:15:18 +00:00
num_tabs + = 1 ;
2023-06-17 06:29:27 +00:00
} else {
2024-03-23 21:10:59 +00:00
webkit_web_view_evaluate_javascript ( notebook_get_webview ( notebook ) , " alert('Too many tabs, not opening a new one') " ,
- 1 , NULL , " rosenrot-alert-numtabs " , NULL , NULL , NULL ) ;
2023-06-17 06:29:27 +00:00
}
2022-11-14 20:41:43 +00:00
}
2024-02-11 16:14:01 +00:00
/* Top bar */
2024-03-24 11:07:29 +00:00
void toggle_bar ( GtkNotebook * notebook , Bar_entry_mode mode )
2022-11-14 20:41:43 +00:00
{
2024-03-24 11:07:29 +00:00
bar . entry_mode = mode ;
2024-03-22 10:48:49 +00:00
switch ( bar . entry_mode ) {
2024-03-23 20:48:42 +00:00
case _SEARCH : {
const char * url = webkit_web_view_get_uri ( notebook_get_webview ( notebook ) ) ;
gtk_entry_set_placeholder_text ( bar . line , " Search " ) ;
gtk_entry_buffer_set_text ( bar . line_text , url , strlen ( url ) ) ;
2024-07-21 14:44:45 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 1 ) ;
2024-03-23 20:48:42 +00:00
gtk_window_set_focus ( window , GTK_WIDGET ( bar . line ) ) ;
break ;
}
case _FIND : {
const char * search_text = webkit_find_controller_get_search_text (
webkit_web_view_get_find_controller ( notebook_get_webview ( notebook ) ) ) ;
2023-03-28 16:14:13 +00:00
2024-03-23 20:48:42 +00:00
if ( search_text ! = NULL )
gtk_entry_buffer_set_text ( bar . line_text , search_text , strlen ( search_text ) ) ;
2023-03-28 16:14:13 +00:00
2024-03-23 20:48:42 +00:00
gtk_entry_set_placeholder_text ( bar . line , " Find " ) ;
2024-07-21 14:44:45 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 1 ) ;
2024-03-23 20:48:42 +00:00
gtk_window_set_focus ( window , GTK_WIDGET ( bar . line ) ) ;
break ;
}
case _HIDDEN :
2024-07-21 14:44:45 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 0 ) ;
2023-03-28 16:14:13 +00:00
}
2022-11-14 20:41:43 +00:00
}
2024-03-24 11:07:29 +00:00
2024-02-11 16:15:24 +00:00
// Handle what happens when the user is on the bar and presses enter
2024-07-21 14:44:45 +00:00
void handle_signal_bar_press_enter ( GtkEntry * self , GtkNotebook * notebook ) /* consider passing notebook as the data here? */
2024-02-11 16:14:01 +00:00
{
2024-07-21 14:44:45 +00:00
WebKitWebView * view = notebook_get_webview ( notebook ) ;
2024-02-11 16:14:01 +00:00
if ( bar . entry_mode = = _SEARCH )
2024-07-21 14:44:45 +00:00
load_uri ( view , gtk_entry_buffer_get_text ( bar . line_text ) ) ;
2024-02-11 16:14:01 +00:00
else if ( bar . entry_mode = = _FIND )
webkit_find_controller_search (
2024-07-21 14:44:45 +00:00
webkit_web_view_get_find_controller ( view ) ,
2024-02-11 16:14:01 +00:00
gtk_entry_buffer_get_text ( bar . line_text ) ,
WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | WEBKIT_FIND_OPTIONS_WRAP_AROUND ,
G_MAXUINT ) ;
gtk_widget_hide ( GTK_WIDGET ( bar . widget ) ) ;
}
2024-07-23 01:54:36 +00:00
/* Shortcuts */
2024-07-21 14:44:45 +00:00
int handle_shortcut ( func id )
2022-11-14 20:41:43 +00:00
{
2024-03-24 11:45:21 +00:00
static double zoom = ZOOM_START_LEVEL ;
2023-03-28 16:14:13 +00:00
static bool is_fullscreen = 0 ;
2022-11-14 20:41:43 +00:00
2024-02-11 17:23:04 +00:00
WebKitWebView * view = notebook_get_webview ( notebook ) ;
2024-07-21 14:44:45 +00:00
NULLCHECK ( notebook ) ;
NULLCHECK ( view ) ;
2024-02-11 17:23:04 +00:00
2023-03-28 16:14:13 +00:00
switch ( id ) {
2024-03-23 20:48:42 +00:00
case goback :
webkit_web_view_go_back ( view ) ;
2023-03-28 16:14:13 +00:00
break ;
2024-03-23 20:48:42 +00:00
case goforward :
webkit_web_view_go_forward ( view ) ;
2023-03-28 16:14:13 +00:00
break ;
2023-02-05 02:11:56 +00:00
2024-07-22 23:29:15 +00:00
case toggle_custom_style :
custom_style_enabled ^ = 1 ;
// fallthrough
2024-03-23 20:48:42 +00:00
case refresh :
webkit_web_view_reload ( view ) ;
break ;
case refresh_force :
webkit_web_view_reload_bypass_cache ( view ) ;
break ;
2023-02-05 02:11:56 +00:00
2024-03-23 20:48:42 +00:00
case back_to_home :
load_uri ( view , HOME ) ;
break ;
2023-02-05 02:11:56 +00:00
2024-03-23 20:48:42 +00:00
case zoomin :
webkit_web_view_set_zoom_level ( view ,
2024-03-24 11:45:21 +00:00
( zoom + = ZOOM_STEPSIZE ) ) ;
2024-03-23 20:48:42 +00:00
break ;
case zoomout :
webkit_web_view_set_zoom_level ( view ,
2024-03-24 11:45:21 +00:00
( zoom - = ZOOM_STEPSIZE ) ) ;
2024-03-23 20:48:42 +00:00
break ;
case zoom_reset :
webkit_web_view_set_zoom_level ( view ,
2024-03-24 11:45:21 +00:00
( zoom = ZOOM_START_LEVEL ) ) ;
2024-03-23 20:48:42 +00:00
break ;
2023-02-05 02:11:56 +00:00
2024-03-23 20:48:42 +00:00
case prev_tab : ; // declarations aren't statements
2024-03-24 11:45:21 +00:00
// https://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement
2024-03-23 20:48:42 +00:00
int n = gtk_notebook_get_n_pages ( notebook ) ;
int k = gtk_notebook_get_current_page ( notebook ) ;
2024-07-22 23:29:15 +00:00
int o = ( n + k - 1 ) % n ;
gtk_notebook_set_current_page ( notebook , o ) ;
2024-03-23 20:48:42 +00:00
break ;
case next_tab : ;
int m = gtk_notebook_get_n_pages ( notebook ) ;
2024-07-22 23:29:15 +00:00
int l = gtk_notebook_get_current_page ( notebook ) ;
int p = ( l + 1 ) % m ;
gtk_notebook_set_current_page ( notebook , p ) ;
2024-03-23 20:48:42 +00:00
break ;
case close_tab :
num_tabs - = 1 ;
2024-07-23 01:54:36 +00:00
switch ( num_tabs ) {
case 0 :
exit ( 0 ) ;
break ;
case 1 :
gtk_notebook_set_show_tabs ( notebook , false ) ;
// fallthrough
default :
gtk_notebook_remove_page ( notebook , gtk_notebook_get_current_page ( notebook ) ) ;
2024-03-23 20:48:42 +00:00
}
break ;
case toggle_fullscreen :
if ( is_fullscreen )
gtk_window_unfullscreen ( window ) ;
else
gtk_window_fullscreen ( window ) ;
is_fullscreen = ! is_fullscreen ;
break ;
case show_searchbar :
2024-03-24 11:07:29 +00:00
toggle_bar ( notebook , _SEARCH ) ;
2024-03-23 20:48:42 +00:00
break ;
case show_finder :
2024-03-24 11:07:29 +00:00
toggle_bar ( notebook , _FIND ) ;
2024-03-23 20:48:42 +00:00
break ;
case finder_next :
2024-03-23 21:10:59 +00:00
webkit_find_controller_search_next ( webkit_web_view_get_find_controller ( view ) ) ;
2024-03-23 20:48:42 +00:00
break ;
case finder_prev :
2024-03-23 21:10:59 +00:00
webkit_find_controller_search_previous ( webkit_web_view_get_find_controller ( view ) ) ;
2024-03-23 20:48:42 +00:00
break ;
case new_tab :
notebook_create_new_tab ( notebook , NULL ) ;
gtk_notebook_set_show_tabs ( notebook , true ) ;
2024-03-24 11:07:29 +00:00
toggle_bar ( notebook , _SEARCH ) ;
2024-03-23 20:48:42 +00:00
break ;
case hide_bar :
2024-07-21 14:44:45 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 0 ) ;
2024-03-24 11:07:29 +00:00
toggle_bar ( notebook , _HIDDEN ) ;
2024-03-23 20:48:42 +00:00
break ;
2024-07-22 23:04:39 +00:00
case halve_window :
2024-07-23 01:54:36 +00:00
gtk_window_set_default_size ( window , FULL_WIDTH / 2 , HEIGHT ) ;
2024-07-22 23:04:39 +00:00
break ;
case rebig_window :
2024-07-23 01:54:36 +00:00
gtk_window_set_default_size ( window , FULL_WIDTH , HEIGHT ) ;
2024-07-22 23:04:39 +00:00
break ;
2024-03-23 20:48:42 +00:00
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 ;
2023-03-28 16:14:13 +00:00
}
}
return 1 ;
2022-11-14 20:41:43 +00:00
}
2024-02-11 16:26:20 +00:00
2024-07-21 14:44:45 +00:00
/* Listen to keypresses */
2022-11-14 20:41:43 +00:00
2024-07-21 14:44:45 +00:00
static int handle_signal_keypress ( void * self , int keyval , int keycode ,
GdkModifierType state , void * controller )
2024-07-21 00:02:19 +00:00
{
2024-07-21 14:44:45 +00:00
if ( 0 ) {
printf ( " New keypress \n " ) ;
2024-07-21 00:02:19 +00:00
printf ( " Keypress state: %d \n " , state ) ;
printf ( " Keypress value: %d \n " , keyval ) ;
}
2024-07-21 14:44:45 +00:00
for ( int i = 0 ; i < sizeof ( shortcut ) / sizeof ( shortcut [ 0 ] ) ; i + + ) {
2024-07-21 00:02:19 +00:00
if ( ( state & shortcut [ i ] . mod | | shortcut [ i ] . mod = = 0x0 ) & & keyval = = shortcut [ i ] . key ) {
2024-07-21 14:44:45 +00:00
printf ( " New shortcut, with id: %d \n " , shortcut [ i ] . id ) ;
return handle_shortcut ( shortcut [ i ] . id ) ;
2024-07-21 00:02:19 +00:00
}
}
2024-07-21 01:48:06 +00:00
return 0 ;
2024-07-21 00:02:19 +00:00
}
2024-02-11 12:52:38 +00:00
int main ( int argc , char * * argv )
2022-11-14 20:41:43 +00:00
{
2024-07-22 23:29:15 +00:00
// Initialize GTK in general
2024-07-20 22:37:14 +00:00
gtk_init ( ) ;
2024-07-22 23:29:15 +00:00
g_object_set ( gtk_settings_get_default ( ) , GTK_SETTINGS_CONFIG_H , NULL ) ;
// https://docs.gtk.org/gobject/method.Object.set.html
2024-07-21 14:44:45 +00:00
GtkCssProvider * css = gtk_css_provider_new ( ) ;
2024-07-21 15:09:33 +00:00
gtk_css_provider_load_from_path ( css , " /opt/rosenrot/style-gtk4.css " ) ;
2024-07-21 14:44:45 +00:00
gtk_style_context_add_provider_for_display ( gdk_display_get_default ( ) , GTK_STYLE_PROVIDER ( css ) , GTK_STYLE_PROVIDER_PRIORITY_USER ) ;
// Create the main window
window = GTK_WINDOW ( gtk_window_new ( ) ) ;
2024-07-23 01:54:36 +00:00
gtk_window_set_default_size ( window , WIDTH , HEIGHT ) ;
2024-02-11 15:57:06 +00:00
2024-07-21 14:44:45 +00:00
// Set up notebook
2024-02-11 15:57:06 +00:00
notebook = GTK_NOTEBOOK ( gtk_notebook_new ( ) ) ;
gtk_notebook_set_show_tabs ( notebook , false ) ;
gtk_notebook_set_show_border ( notebook , false ) ;
2024-07-21 00:35:15 +00:00
gtk_window_set_child ( window , GTK_WIDGET ( notebook ) ) ;
2024-02-11 15:29:36 +00:00
2024-07-22 23:29:15 +00:00
// Set up top bar
2024-02-11 15:57:06 +00:00
bar . line_text = GTK_ENTRY_BUFFER ( gtk_entry_buffer_new ( " " , 0 ) ) ;
bar . line = GTK_ENTRY ( gtk_entry_new_with_buffer ( bar . line_text ) ) ;
2024-07-22 23:29:15 +00:00
gtk_entry_set_alignment ( bar . line , 0.5 ) ;
2024-07-22 23:04:39 +00:00
gtk_widget_set_size_request ( GTK_WIDGET ( bar . line ) , BAR_WIDTH , - 1 ) ;
2024-02-11 15:57:06 +00:00
bar . widget = GTK_HEADER_BAR ( gtk_header_bar_new ( ) ) ;
2024-07-21 14:44:45 +00:00
gtk_header_bar_set_title_widget ( bar . widget , GTK_WIDGET ( bar . line ) ) ;
2024-02-11 15:29:36 +00:00
gtk_window_set_titlebar ( window , GTK_WIDGET ( bar . widget ) ) ;
2023-03-28 16:14:13 +00:00
2024-07-22 23:29:15 +00:00
// Setup signals
2024-07-21 14:44:45 +00:00
GtkEventController * event_controller = gtk_event_controller_key_new ( ) ;
g_signal_connect ( event_controller , " key-pressed " , G_CALLBACK ( handle_signal_keypress ) , NULL ) ;
gtk_widget_add_controller ( GTK_WIDGET ( window ) , event_controller ) ;
g_signal_connect ( bar . line , " activate " , G_CALLBACK ( handle_signal_bar_press_enter ) , notebook ) ;
g_signal_connect ( GTK_WIDGET ( window ) , " destroy " , G_CALLBACK ( exit ) , notebook ) ;
2024-07-23 01:54:36 +00:00
// Load first tab
2023-06-26 10:26:53 +00:00
char * first_uri = argc > 1 ? argv [ 1 ] : HOME ;
2024-02-11 16:15:24 +00:00
notebook_create_new_tab ( notebook , first_uri ) ;
2024-02-11 15:29:36 +00:00
2024-07-22 23:29:15 +00:00
// Show to user
// The first two commands are redundant with notebook_create_new_tab
gtk_window_present ( window ) ;
2024-07-21 14:44:45 +00:00
gtk_widget_set_visible ( GTK_WIDGET ( window ) , 1 ) ;
if ( argc ! = 0 ) gtk_widget_set_visible ( GTK_WIDGET ( bar . widget ) , 0 ) ;
2023-03-28 16:14:13 +00:00
2024-07-22 23:29:15 +00:00
// Deal with more tabs, if any
2023-03-28 16:14:13 +00:00
if ( argc > 2 ) {
gtk_notebook_set_show_tabs ( notebook , true ) ;
for ( int i = 2 ; i < argc ; i + + ) {
2024-02-11 16:15:24 +00:00
notebook_create_new_tab ( notebook , argv [ i ] ) ;
2023-03-28 16:14:13 +00:00
}
}
2022-11-14 20:41:43 +00:00
2024-07-21 14:44:45 +00:00
// Enter the main event loop, and wait for user interaction
while ( g_list_model_get_n_items ( gtk_window_get_toplevels ( ) ) > 0 & & num_tabs > 0 )
2024-07-21 01:48:06 +00:00
g_main_context_iteration ( NULL , TRUE ) ;
2024-07-21 14:44:45 +00:00
return 0 ;
2022-11-14 20:41:43 +00:00
}