fix double keypress events
This commit is contained in:
parent
a54d55ee3f
commit
e189704eb5
8
makefile
8
makefile
|
@ -3,7 +3,13 @@ CFLAGS = `pkg-config --cflags gtk4 webkit2gtk-5.0`
|
|||
LIBS = `pkg-config --libs gtk4 webkit2gtk-5.0`
|
||||
|
||||
all:
|
||||
${CC} -fPIC -g -O3 -o rose *.c $(CFLAGS) $(LIBS) && ./rose
|
||||
${CC} -fPIC -g -O3 -o rose *.c $(CFLAGS) $(LIBS)
|
||||
strip ./rose
|
||||
|
||||
install: all
|
||||
cp -uf ./rose /usr/local/bin/rose
|
||||
mkdir -p /usr/local/share/rose
|
||||
cp -uf ./youtube.js /usr/local/share/rose/youtube.js
|
||||
|
||||
clean:
|
||||
rm -f rose compile_flags.txt
|
||||
|
|
134
rose.c
134
rose.c
|
@ -1,138 +1,24 @@
|
|||
#include "rose.h"
|
||||
#include "config.h"
|
||||
#include "webview.h"
|
||||
#include "window.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct Client {
|
||||
GtkWidget *window;
|
||||
WebKitWebView *webview;
|
||||
} Client;
|
||||
|
||||
WebKitWebView* new_webview()
|
||||
{
|
||||
char cookiefile[64];
|
||||
WebKitWebView *webview;
|
||||
WebKitCookieManager *cookiemanager;
|
||||
WebKitUserContentManager *contentmanager;
|
||||
|
||||
WebKitSettings *settings = webkit_settings_new_with_settings(
|
||||
"auto-load-images", true,
|
||||
"enable-back-forward-navigation-gestures", true,
|
||||
"enable-developer-extras", true,
|
||||
"enable-media-stream", true,
|
||||
"hardware-acceleration-policy", WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS,
|
||||
"javascript-can-access-clipboard", true, NULL);
|
||||
|
||||
WebKitWebContext *context = webkit_web_context_new_with_website_data_manager(
|
||||
webkit_website_data_manager_new(
|
||||
"base-cache-directory", cachedir,
|
||||
"base-data-directory", cachedir,
|
||||
NULL));
|
||||
|
||||
webkit_settings_set_user_agent_with_application_details(
|
||||
settings, "Mini", "0.1");
|
||||
|
||||
webkit_web_context_set_process_model(context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
|
||||
webkit_web_context_set_cache_model(context, WEBKIT_CACHE_MODEL_WEB_BROWSER);
|
||||
contentmanager = webkit_user_content_manager_new();
|
||||
cookiemanager = webkit_web_context_get_cookie_manager(context);
|
||||
|
||||
strcpy(cookiefile, cachedir);
|
||||
strcat(cookiefile, "cookies");
|
||||
|
||||
webkit_cookie_manager_set_persistent_storage(cookiemanager,
|
||||
cookiefile, WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
|
||||
|
||||
webkit_cookie_manager_set_accept_policy(cookiemanager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
|
||||
|
||||
return g_object_new(
|
||||
WEBKIT_TYPE_WEB_VIEW,
|
||||
"settings", settings,
|
||||
"user-content-manager", contentmanager,
|
||||
"web-context", context, NULL);
|
||||
}
|
||||
|
||||
static gboolean winevent(Client* c,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
GdkModifierType state)
|
||||
{
|
||||
if (state == GDK_CONTROL_MASK) {
|
||||
switch (keycode) {
|
||||
case 43: {
|
||||
if (webkit_web_view_can_go_back(c->webview))
|
||||
webkit_web_view_go_back(c->webview);
|
||||
} break;
|
||||
case 46: {
|
||||
if (webkit_web_view_can_go_forward(c->webview))
|
||||
webkit_web_view_go_forward(c->webview);
|
||||
} break;
|
||||
case 26: {
|
||||
webkit_web_view_load_uri(c->webview, homepage);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void _history_append(const char *url,
|
||||
const char* title)
|
||||
{
|
||||
char filename[] = "history";
|
||||
char *path = calloc(1, sizeof(char) * (strlen(cachedir) + strlen(filename)) + 1);
|
||||
strcpy(path, cachedir);
|
||||
strcat(path, filename);
|
||||
|
||||
FILE *f;
|
||||
|
||||
if (!(f = fopen(path, "r"))) {
|
||||
f = fopen(path, "w");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
f = fopen(path, "a");
|
||||
|
||||
fprintf(f, "'%s' - %s", title, url);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void history_append(WebKitWebView *webview,
|
||||
WebKitLoadEvent event,
|
||||
gpointer userdata)
|
||||
{
|
||||
if (event == WEBKIT_LOAD_FINISHED) {
|
||||
const char *uri = webkit_web_view_get_uri(webview);
|
||||
const char *title = webkit_web_view_get_title(webview);
|
||||
_history_append(uri, title);
|
||||
}
|
||||
}
|
||||
|
||||
static void run(GtkApplication *app)
|
||||
{
|
||||
if (dark_mode)
|
||||
RoseWindow *window = rose_window_new(app);
|
||||
GtkWidget *webview = rose_webview_new();
|
||||
|
||||
if (dark_mode) {
|
||||
g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", true, NULL);
|
||||
}
|
||||
|
||||
Client *c = calloc(1, sizeof(Client));
|
||||
|
||||
c->window = gtk_window_new();
|
||||
c->webview = new_webview();
|
||||
|
||||
gtk_application_add_window(app, GTK_WINDOW(c->window));
|
||||
rose_window_set_webview(window, webview);
|
||||
rose_window_show(window);
|
||||
|
||||
if (homepage)
|
||||
webkit_web_view_load_uri(c->webview, homepage);
|
||||
|
||||
gtk_window_set_child(GTK_WINDOW(c->window), GTK_WIDGET(c->webview));
|
||||
|
||||
GtkEventController *controller = gtk_event_controller_key_new();
|
||||
gtk_widget_add_controller(GTK_WIDGET(c->window), controller);
|
||||
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
|
||||
g_signal_connect_swapped(controller, "key-pressed", G_CALLBACK (winevent), c);
|
||||
|
||||
g_signal_connect(c->webview, "load-changed", G_CALLBACK(history_append), NULL);
|
||||
|
||||
gtk_widget_show(GTK_WIDGET(c->window));
|
||||
rose_webview_load_url(WEBKIT_WEB_VIEW(webview), homepage);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
153
webview.c
Normal file
153
webview.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
#include "webview.h"
|
||||
#include "config.h"
|
||||
|
||||
struct _RoseWebView {
|
||||
WebKitWebView parent_instance;
|
||||
|
||||
GCancellable *cancellable;
|
||||
RoseWebViewNavigationFlags navigation;
|
||||
|
||||
char *address;
|
||||
};
|
||||
|
||||
enum {
|
||||
LAST_PROP,
|
||||
PROP_NAVIGATION,
|
||||
PROP_ADDRESS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_properties[LAST_PROP];
|
||||
|
||||
G_DEFINE_TYPE(RoseWebView, rose_webview, WEBKIT_TYPE_WEB_VIEW)
|
||||
|
||||
static void update_navigation_flags(RoseWebView *webview)
|
||||
{
|
||||
guint flags = 0;
|
||||
if (webkit_web_view_can_go_back(WEBKIT_WEB_VIEW(webview)))
|
||||
flags |= ROSE_WEBVIEW_NAV_BACK;
|
||||
|
||||
if (webkit_web_view_can_go_forward(WEBKIT_WEB_VIEW(webview)))
|
||||
flags |= ROSE_WEBVIEW_FORWARD;
|
||||
|
||||
if (webview->navigation != (RoseWebViewNavigationFlags) flags) {
|
||||
webview->navigation = (RoseWebViewNavigationFlags) flags;
|
||||
g_object_notify_by_pspec(G_OBJECT(webview), obj_properties[PROP_NAVIGATION]);
|
||||
}
|
||||
}
|
||||
|
||||
static void rose_webview_constructed(GObject *object)
|
||||
{
|
||||
RoseWebView *webview = ROSE_WEBVIEW(object);
|
||||
g_auto(GStrv) cors_allowlist = NULL;
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
|
||||
G_OBJECT_CLASS(rose_webview_parent_class)->constructed (object);
|
||||
|
||||
g_signal_connect_swapped(webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(webview)),
|
||||
"changed", G_CALLBACK(update_navigation_flags), webview);
|
||||
|
||||
context = gtk_widget_get_style_context(GTK_WIDGET(webview));
|
||||
|
||||
if (gtk_style_context_lookup_color(context, "theme_base_color", &color))
|
||||
webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(webview), &color);
|
||||
|
||||
cors_allowlist = g_new(char*, 2);
|
||||
cors_allowlist[0] = g_strdup("rose-resource://*/*");
|
||||
cors_allowlist[1] = NULL;
|
||||
|
||||
webkit_web_view_set_cors_allowlist(WEBKIT_WEB_VIEW(webview), (const char* const *) cors_allowlist);
|
||||
}
|
||||
|
||||
static void rose_webview_dispose(GObject *object)
|
||||
{
|
||||
RoseWebView *webview = ROSE_WEBVIEW(object);
|
||||
WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(webview));
|
||||
|
||||
if (webview->cancellable) {
|
||||
g_cancellable_cancel(webview->cancellable);
|
||||
g_clear_object(&webview->cancellable);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(rose_webview_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void rose_webview_finalize(GObject *object)
|
||||
{
|
||||
RoseWebView *view = ROSE_WEBVIEW(object);
|
||||
|
||||
g_free(view->address);
|
||||
|
||||
G_OBJECT_CLASS(rose_webview_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void rose_webview_class_init(RoseWebViewClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(class);
|
||||
WebKitWebViewClass *webkit_webview_class = WEBKIT_WEB_VIEW_CLASS(class);
|
||||
|
||||
object_class->dispose = rose_webview_dispose;
|
||||
object_class->finalize = rose_webview_finalize;
|
||||
object_class->constructed = rose_webview_constructed;
|
||||
|
||||
obj_properties[PROP_ADDRESS] =
|
||||
g_param_spec_string ("address",
|
||||
"Address",
|
||||
"address",
|
||||
"",
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void rose_webview_init(RoseWebView *webview)
|
||||
{
|
||||
gtk_widget_set_overflow(GTK_WIDGET(webview), GTK_OVERFLOW_HIDDEN);
|
||||
}
|
||||
|
||||
void rose_webview_load_url(WebKitWebView *webview, const char *url)
|
||||
{
|
||||
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), url);
|
||||
}
|
||||
|
||||
GtkWidget* rose_webview_new()
|
||||
{
|
||||
char cookiefile[64];
|
||||
WebKitWebView *webview;
|
||||
WebKitCookieManager *cookiemanager;
|
||||
WebKitUserContentManager *contentmanager;
|
||||
|
||||
WebKitSettings *settings = webkit_settings_new_with_settings(
|
||||
"auto-load-images", true,
|
||||
"enable-back-forward-navigation-gestures", true,
|
||||
"enable-developer-extras", true,
|
||||
"enable-media-stream", true,
|
||||
"hardware-acceleration-policy", WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS,
|
||||
"javascript-can-access-clipboard", true, NULL);
|
||||
|
||||
WebKitWebContext *context = webkit_web_context_new_with_website_data_manager(
|
||||
webkit_website_data_manager_new(
|
||||
"base-cache-directory", cachedir,
|
||||
"base-data-directory", cachedir,
|
||||
NULL));
|
||||
|
||||
webkit_settings_set_user_agent_with_application_details(
|
||||
settings, "Mini", "0.1");
|
||||
|
||||
webkit_web_context_set_process_model(context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
|
||||
webkit_web_context_set_cache_model(context, WEBKIT_CACHE_MODEL_WEB_BROWSER);
|
||||
contentmanager = webkit_user_content_manager_new();
|
||||
cookiemanager = webkit_web_context_get_cookie_manager(context);
|
||||
|
||||
strcpy(cookiefile, cachedir);
|
||||
strcat(cookiefile, "cookies");
|
||||
|
||||
webkit_cookie_manager_set_persistent_storage(cookiemanager,
|
||||
cookiefile, WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
|
||||
|
||||
webkit_cookie_manager_set_accept_policy(cookiemanager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
|
||||
|
||||
return g_object_new(
|
||||
WEBKIT_TYPE_WEB_VIEW,
|
||||
"settings", settings,
|
||||
"user-content-manager", contentmanager,
|
||||
"web-context", context, NULL);
|
||||
}
|
26
webview.h
Normal file
26
webview.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <webkit2/webkit2.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define ROSE_TYPE_WEBVIEW rose_webview_get_type()
|
||||
|
||||
G_DECLARE_FINAL_TYPE(RoseWebView, rose_webview, ROSE, WEBVIEW, WebKitWebView)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ROSE_WEBVIEW_NAV_BACK = 1 << 0,
|
||||
ROSE_WEBVIEW_FORWARD = 1 << 1
|
||||
} RoseWebViewNavigationFlags;
|
||||
|
||||
GtkWidget* rose_webview_new();
|
||||
void rose_webview_load_url(WebKitWebView *webview, const char *url);
|
||||
|
||||
RoseWebViewNavigationFlags rose_webview_get_navigation_flags(RoseWebView *webview);
|
||||
|
||||
void rose_webview_go_back(RoseWebView *window);
|
||||
void rose_webview_go_forward(RoseWebView *window);
|
||||
|
||||
const char* rose_webview_get_address(RoseWebView *webview);
|
103
window.c
Normal file
103
window.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
#include "window.h"
|
||||
/* #include "gestures.h" */
|
||||
#include "config.h"
|
||||
#include "webview.h"
|
||||
|
||||
struct _RoseWindow {
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
GtkWindow *window;
|
||||
WebKitWebView *webview;
|
||||
GHashTable *action_groups;
|
||||
GHashTable *action_labels;
|
||||
/* RoseGestureController *mouse_gesture_controller; */
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_ACTIVE_CHILD
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(RoseWindow, rose_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static gboolean key_press_callback(WebKitWebView *webview,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
GdkModifierType state)
|
||||
{
|
||||
|
||||
if (state & GDK_CONTROL_MASK) {
|
||||
switch (keycode) {
|
||||
case 43: {
|
||||
webkit_web_view_go_back(webview);
|
||||
} break;
|
||||
case 46: {
|
||||
webkit_web_view_go_forward(webview);
|
||||
} break;
|
||||
case 26: {
|
||||
rose_webview_load_url(webview, homepage);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void rose_window_constructed(GObject *object)
|
||||
{
|
||||
RoseWindow *window;
|
||||
GAction *action;
|
||||
GActionGroup *action_group;
|
||||
GSimpleActionGroup *simple_action_group;
|
||||
guint i;
|
||||
GApplication *app;
|
||||
GtkEventController *controller;
|
||||
|
||||
G_OBJECT_CLASS(rose_window_parent_class)->constructed(object);
|
||||
|
||||
window = ROSE_WINDOW(window);
|
||||
}
|
||||
|
||||
static void rose_window_init(RoseWindow *window)
|
||||
{
|
||||
window->window = GTK_WINDOW(gtk_window_new());
|
||||
}
|
||||
|
||||
void rose_window_show(RoseWindow *window)
|
||||
{
|
||||
GtkWidget *w = gtk_window_new();
|
||||
gtk_window_set_child(GTK_WINDOW(w), GTK_WIDGET(window->webview));
|
||||
|
||||
/* Keyboard shortcuts */
|
||||
GtkEventController *controller;
|
||||
controller = gtk_event_controller_key_new();
|
||||
g_signal_connect_swapped(controller, "key-pressed", G_CALLBACK(key_press_callback), window->webview);
|
||||
gtk_widget_add_controller(GTK_WIDGET(w), controller);
|
||||
|
||||
gtk_widget_show(w);
|
||||
}
|
||||
|
||||
void rose_window_set_webview(RoseWindow *window, GtkWidget *webview)
|
||||
{
|
||||
window->webview = WEBKIT_WEB_VIEW(webview);
|
||||
}
|
||||
|
||||
static void rose_window_class_init(RoseWindowClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(class);
|
||||
GtkApplicationWindowClass *window_class = GTK_APPLICATION_WINDOW_CLASS(class);
|
||||
|
||||
object_class->constructed = rose_window_constructed;
|
||||
|
||||
/* g_object_class_override_property(object_class, */
|
||||
/* PROP_ACTIVE_CHILD, */
|
||||
/* "active-child"); */
|
||||
}
|
||||
|
||||
RoseWindow* rose_window_new(GtkApplication *app)
|
||||
{
|
||||
return g_object_new(
|
||||
GTK_TYPE_APPLICATION_WINDOW,
|
||||
"application", GTK_APPLICATION(app),
|
||||
NULL
|
||||
);
|
||||
}
|
21
window.h
Normal file
21
window.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "webview.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define ROSE_TYPE_WINDOW rose_window_get_type()
|
||||
|
||||
G_DECLARE_FINAL_TYPE(RoseWindow, rose_window, ROSE, WINDOW, GtkApplicationWindow)
|
||||
|
||||
RoseWindow* rose_window_new();
|
||||
void rose_window_show(RoseWindow *window);
|
||||
gboolean rose_window_close(RoseWindow *window);
|
||||
|
||||
void rose_window_set_webview(RoseWindow *window, GtkWidget *webview);
|
||||
|
||||
GActionGroup* rose_window_get_action_group(RoseWindow *window,
|
||||
const char *prefix);
|
||||
|
||||
G_END_DECLS
|
Loading…
Reference in New Issue
Block a user