mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-25 13:37:02 +03:00
add nsgtk support for core window API
This commit is contained in:
parent
ea84f67035
commit
ca5b165c85
@ -163,7 +163,7 @@ S_FRONTEND := gui.c schedule.c layout_pango.c bitmap.c plotters.c \
|
||||
selection.c history.c window.c fetch.c download.c menu.c \
|
||||
print.c search.c tabs.c toolbar.c gettext.c \
|
||||
compat.c cookies.c hotlist.c viewdata.c viewsource.c \
|
||||
preferences.c about.c ssl_cert.c resources.c
|
||||
preferences.c about.c ssl_cert.c resources.c corewindow.c
|
||||
|
||||
# This is the final source build list
|
||||
# Note this is deliberately *not* expanded here as common and image
|
||||
|
638
frontends/gtk/corewindow.c
Normal file
638
frontends/gtk/corewindow.c
Normal file
@ -0,0 +1,638 @@
|
||||
/*
|
||||
* Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* NetSurf is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* GTK generic core window interface.
|
||||
*
|
||||
* Provides interface for core renderers to the gtk toolkit drawable area.
|
||||
* \todo should the interface really be called coredrawable?
|
||||
*
|
||||
|
||||
* This module is an object that must be encapsulated. Client users
|
||||
* should embed a struct nsgtk_corewindow at the beginning of their
|
||||
* context for this display surface, fill in relevant data and then
|
||||
* call nsgtk_corewindow_init()
|
||||
*
|
||||
* The nsgtk core window structure requires the drawing area and
|
||||
* scrollable widgets are present and the callback for draw, key and
|
||||
* mouse operations.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "utils/log.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/messages.h"
|
||||
#include "utils/utf8.h"
|
||||
#include "netsurf/keypress.h"
|
||||
#include "netsurf/mouse.h"
|
||||
#include "desktop/plot_style.h"
|
||||
|
||||
#include "gtk/compat.h"
|
||||
#include "gtk/gui.h" /* just for gtk_gui_gdkkey_to_nskey */
|
||||
#include "gtk/plotters.h"
|
||||
#include "gtk/corewindow.h"
|
||||
|
||||
/**
|
||||
* Convert GDK mouse event to netsurf mouse state
|
||||
*/
|
||||
static browser_mouse_state nsgtk_cw_gdkbutton_to_nsstate(GdkEventButton *event)
|
||||
{
|
||||
browser_mouse_state ms;
|
||||
|
||||
if (event->type == GDK_2BUTTON_PRESS) {
|
||||
ms = BROWSER_MOUSE_DOUBLE_CLICK;
|
||||
} else {
|
||||
ms = BROWSER_MOUSE_HOVER;
|
||||
}
|
||||
|
||||
/* button state */
|
||||
switch (event->button) {
|
||||
case 1:
|
||||
ms |= BROWSER_MOUSE_PRESS_1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ms |= BROWSER_MOUSE_PRESS_2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle the modifiers too */
|
||||
if (event->state & GDK_SHIFT_MASK) {
|
||||
ms |= BROWSER_MOUSE_MOD_1;
|
||||
}
|
||||
|
||||
if (event->state & GDK_CONTROL_MASK) {
|
||||
ms |= BROWSER_MOUSE_MOD_2;
|
||||
}
|
||||
|
||||
if (event->state & GDK_MOD1_MASK) {
|
||||
ms |= BROWSER_MOUSE_MOD_3;
|
||||
}
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk event on mouse button press.
|
||||
*
|
||||
* \param widget The gtk widget the event occoured for.
|
||||
* \param event The event that occoured.
|
||||
* \param g The context pointer passed when teh event was registered.
|
||||
*/
|
||||
static gboolean
|
||||
nsgtk_cw_button_press_event(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
|
||||
|
||||
gtk_im_context_reset(nsgtk_cw->input_method);
|
||||
gtk_widget_grab_focus(GTK_WIDGET(nsgtk_cw->drawing_area));
|
||||
|
||||
/* record event information for potentially starting a drag. */
|
||||
mouse->pressed_x = mouse->last_x = event->x;
|
||||
mouse->pressed_y = mouse->last_y = event->y;
|
||||
mouse->pressed = true;
|
||||
|
||||
mouse->state = nsgtk_cw_gdkbutton_to_nsstate(event);
|
||||
|
||||
nsgtk_cw->mouse(nsgtk_cw, mouse->state, event->x, event->y);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nsgtk_cw_button_release_event(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
|
||||
|
||||
/* only button 1 clicks are considered double clicks. If the
|
||||
* mouse state is PRESS then we are waiting for a release to
|
||||
* emit a click event, otherwise just reset the state to nothing.
|
||||
*/
|
||||
if (mouse->state & BROWSER_MOUSE_DOUBLE_CLICK) {
|
||||
if (mouse->state & BROWSER_MOUSE_PRESS_1) {
|
||||
mouse->state ^= BROWSER_MOUSE_PRESS_1 |
|
||||
BROWSER_MOUSE_CLICK_1;
|
||||
} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
|
||||
mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
|
||||
BROWSER_MOUSE_CLICK_2 |
|
||||
BROWSER_MOUSE_DOUBLE_CLICK);
|
||||
}
|
||||
} else if (mouse->state & BROWSER_MOUSE_PRESS_1) {
|
||||
mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
|
||||
BROWSER_MOUSE_CLICK_1);
|
||||
} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
|
||||
mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
|
||||
BROWSER_MOUSE_CLICK_2);
|
||||
} else if (mouse->state & BROWSER_MOUSE_HOLDING_1) {
|
||||
mouse->state ^= (BROWSER_MOUSE_HOLDING_1 |
|
||||
BROWSER_MOUSE_DRAG_ON);
|
||||
} else if (mouse->state & BROWSER_MOUSE_HOLDING_2) {
|
||||
mouse->state ^= (BROWSER_MOUSE_HOLDING_2 |
|
||||
BROWSER_MOUSE_DRAG_ON);
|
||||
}
|
||||
|
||||
/* Handle modifiers being removed */
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
|
||||
!(event->state & GDK_SHIFT_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_1;
|
||||
}
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
|
||||
!(event->state & GDK_CONTROL_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_2;
|
||||
}
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
|
||||
!(event->state & GDK_MOD1_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_3;
|
||||
}
|
||||
|
||||
/* end drag with modifiers */
|
||||
if (mouse->state & (BROWSER_MOUSE_MOD_1 |
|
||||
BROWSER_MOUSE_MOD_2 |
|
||||
BROWSER_MOUSE_MOD_3)) {
|
||||
mouse->state = BROWSER_MOUSE_HOVER;
|
||||
}
|
||||
|
||||
nsgtk_cw->mouse(nsgtk_cw, mouse->state, event->x, event->y);
|
||||
|
||||
mouse->pressed = false;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nsgtk_cw_motion_notify_event(GtkWidget *widget,
|
||||
GdkEventMotion *event, gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
|
||||
|
||||
if (mouse->pressed == false) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((fabs(event->x - mouse->last_x) < 5.0) &&
|
||||
(fabs(event->y - mouse->last_y) < 5.0)) {
|
||||
/* Mouse hasn't moved far enough from press coordinate
|
||||
* for this to be considered a drag.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* This is a drag, ensure it's always treated as such, even if
|
||||
* we drag back over the press location.
|
||||
*/
|
||||
mouse->last_x = INT_MIN;
|
||||
mouse->last_y = INT_MIN;
|
||||
|
||||
|
||||
if (mouse->state & BROWSER_MOUSE_PRESS_1) {
|
||||
/* Start button 1 drag */
|
||||
nsgtk_cw->mouse(nsgtk_cw,
|
||||
BROWSER_MOUSE_DRAG_1,
|
||||
mouse->pressed_x,
|
||||
mouse->pressed_y);
|
||||
|
||||
/* Replace PRESS with HOLDING and declare drag in progress */
|
||||
mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
|
||||
BROWSER_MOUSE_HOLDING_1);
|
||||
mouse->state |= BROWSER_MOUSE_DRAG_ON;
|
||||
|
||||
} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
|
||||
/* Start button 2s drag */
|
||||
nsgtk_cw->mouse(nsgtk_cw,
|
||||
BROWSER_MOUSE_DRAG_2,
|
||||
mouse->pressed_x,
|
||||
mouse->pressed_y);
|
||||
|
||||
/* Replace PRESS with HOLDING and declare drag in progress */
|
||||
mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
|
||||
BROWSER_MOUSE_HOLDING_2);
|
||||
mouse->state |= BROWSER_MOUSE_DRAG_ON;
|
||||
|
||||
} else {
|
||||
/* continue drag */
|
||||
|
||||
/* Handle modifiers being removed */
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
|
||||
!(event->state & GDK_SHIFT_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_1;
|
||||
}
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
|
||||
!(event->state & GDK_CONTROL_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_2;
|
||||
}
|
||||
if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
|
||||
!(event->state & GDK_MOD1_MASK)) {
|
||||
mouse->state ^= BROWSER_MOUSE_MOD_3;
|
||||
}
|
||||
|
||||
if (mouse->state &
|
||||
(BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2)) {
|
||||
nsgtk_cw->mouse(nsgtk_cw,
|
||||
mouse->state,
|
||||
event->x, event->y);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deal with keypress events not handled but input method or callback
|
||||
*
|
||||
* \param nsgtk_cw nsgtk core window key event happened in.
|
||||
* \param nskey The netsurf keycode of the event.
|
||||
* \return NSERROR_OK on sucess otherwise an error code.
|
||||
*/
|
||||
static nserror nsgtk_cw_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
|
||||
{
|
||||
double value;
|
||||
GtkAdjustment *vscroll;
|
||||
GtkAdjustment *hscroll;
|
||||
GtkAdjustment *scroll = NULL;
|
||||
gdouble hpage, vpage;
|
||||
|
||||
vscroll = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
|
||||
hscroll = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
|
||||
g_object_get(vscroll, "page-size", &vpage, NULL);
|
||||
g_object_get(hscroll, "page-size", &hpage, NULL);
|
||||
|
||||
switch(nskey) {
|
||||
case NS_KEY_TEXT_START:
|
||||
scroll = vscroll;
|
||||
value = nsgtk_adjustment_get_lower(scroll);
|
||||
break;
|
||||
|
||||
case NS_KEY_TEXT_END:
|
||||
scroll = vscroll;
|
||||
value = nsgtk_adjustment_get_upper(scroll) - vpage;
|
||||
if (value < nsgtk_adjustment_get_lower(scroll))
|
||||
value = nsgtk_adjustment_get_lower(scroll);
|
||||
break;
|
||||
|
||||
case NS_KEY_LEFT:
|
||||
scroll = hscroll;
|
||||
value = gtk_adjustment_get_value(scroll) -
|
||||
nsgtk_adjustment_get_step_increment(scroll);
|
||||
if (value < nsgtk_adjustment_get_lower(scroll))
|
||||
value = nsgtk_adjustment_get_lower(scroll);
|
||||
break;
|
||||
|
||||
case NS_KEY_RIGHT:
|
||||
scroll = hscroll;
|
||||
value = gtk_adjustment_get_value(scroll) +
|
||||
nsgtk_adjustment_get_step_increment(scroll);
|
||||
if (value > nsgtk_adjustment_get_upper(scroll) - hpage)
|
||||
value = nsgtk_adjustment_get_upper(scroll) - hpage;
|
||||
break;
|
||||
case NS_KEY_UP:
|
||||
scroll = vscroll;
|
||||
value = gtk_adjustment_get_value(scroll) -
|
||||
nsgtk_adjustment_get_step_increment(scroll);
|
||||
if (value < nsgtk_adjustment_get_lower(scroll))
|
||||
value = nsgtk_adjustment_get_lower(scroll);
|
||||
break;
|
||||
|
||||
case NS_KEY_DOWN:
|
||||
scroll = vscroll;
|
||||
value = gtk_adjustment_get_value(scroll) +
|
||||
nsgtk_adjustment_get_step_increment(scroll);
|
||||
if (value > nsgtk_adjustment_get_upper(scroll) - vpage)
|
||||
value = nsgtk_adjustment_get_upper(scroll) - vpage;
|
||||
break;
|
||||
|
||||
case NS_KEY_PAGE_UP:
|
||||
scroll = vscroll;
|
||||
value = gtk_adjustment_get_value(scroll) -
|
||||
nsgtk_adjustment_get_page_increment(scroll);
|
||||
|
||||
if (value < nsgtk_adjustment_get_lower(scroll))
|
||||
value = nsgtk_adjustment_get_lower(scroll);
|
||||
|
||||
break;
|
||||
|
||||
case NS_KEY_PAGE_DOWN:
|
||||
scroll = vscroll;
|
||||
value = gtk_adjustment_get_value(scroll) +
|
||||
nsgtk_adjustment_get_page_increment(scroll);
|
||||
|
||||
if (value > nsgtk_adjustment_get_upper(scroll) - vpage)
|
||||
value = nsgtk_adjustment_get_upper(scroll) - vpage;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (scroll != NULL) {
|
||||
gtk_adjustment_set_value(scroll, value);
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk event on key press.
|
||||
*
|
||||
* \param widget The gtk widget the event occoured for.
|
||||
* \param event The event that occoured.
|
||||
* \param g The context pointer passed when teh event was registered.
|
||||
*/
|
||||
static gboolean
|
||||
nsgtk_cw_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
nserror res;
|
||||
uint32_t nskey;
|
||||
|
||||
/* check to see if gtk input method swallowed the keypress */
|
||||
if (gtk_im_context_filter_keypress(nsgtk_cw->input_method, event)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* convert gtk event to nskey */
|
||||
nskey = gtk_gui_gdkkey_to_nskey(event);
|
||||
|
||||
/* attempt to handle keypress in caller */
|
||||
res = nsgtk_cw->key(nsgtk_cw, nskey);
|
||||
if (res == NSERROR_OK) {
|
||||
return TRUE;
|
||||
} else if (res != NSERROR_NOT_IMPLEMENTED) {
|
||||
LOG("%s", messages_get_errorcode(res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* deal with unprocessed keypress */
|
||||
res = nsgtk_cw_key(nsgtk_cw, nskey);
|
||||
if (res != NSERROR_OK) {
|
||||
LOG("%s", messages_get_errorcode(res));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
nsgtk_cw_keyrelease_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
|
||||
return gtk_im_context_filter_keypress(nsgtk_cw->input_method, event);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsgtk_cw_input_method_commit(GtkIMContext *ctx, const gchar *str, gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
size_t len;
|
||||
size_t offset = 0;
|
||||
uint32_t nskey;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
while (offset < len) {
|
||||
nskey = utf8_to_ucs4(str + offset, len - offset);
|
||||
|
||||
nsgtk_cw->key(nsgtk_cw, nskey);
|
||||
|
||||
offset = utf8_next(str, len, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if GTK_CHECK_VERSION(3,0,0)
|
||||
|
||||
/* signal handler for core window redraw */
|
||||
static gboolean
|
||||
nsgtk_cw_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)data;
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
struct rect clip;
|
||||
|
||||
current_widget = widget;
|
||||
current_cr = cr;
|
||||
|
||||
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
|
||||
|
||||
if (tv->tree_flags == TREE_SSLCERT) {
|
||||
ssl_current_session = tv->ssl_data;
|
||||
}
|
||||
|
||||
clip.x0 = x1;
|
||||
clip.y0 = y1;
|
||||
clip.x1 = x2;
|
||||
clip.y1 = y2;
|
||||
|
||||
nsgtk_cw->draw(nsgtk_cw, &clip);
|
||||
|
||||
current_widget = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* signal handler for core window redraw */
|
||||
static gboolean
|
||||
nsgtk_cw_draw_event(GtkWidget *widget,
|
||||
GdkEventExpose *event,
|
||||
gpointer g)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
|
||||
struct rect clip;
|
||||
|
||||
clip.x0 = event->area.x;
|
||||
clip.y0 = event->area.y;
|
||||
clip.x1 = event->area.x + event->area.width;
|
||||
clip.y1 = event->area.y + event->area.height;
|
||||
|
||||
current_widget = widget;
|
||||
current_cr = gdk_cairo_create(nsgtk_widget_get_window(widget));
|
||||
|
||||
nsgtk_cw->draw(nsgtk_cw, &clip);
|
||||
|
||||
current_widget = NULL;
|
||||
cairo_destroy(current_cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* callback from core to request a redraw
|
||||
*/
|
||||
static void
|
||||
nsgtk_cw_redraw_request(struct core_window *cw, const struct rect *r)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
|
||||
|
||||
gtk_widget_queue_draw_area(GTK_WIDGET(nsgtk_cw->drawing_area),
|
||||
r->x0, r->y0,
|
||||
r->x1 - r->x0, r->y1 - r->y0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsgtk_cw_update_size(struct core_window *cw, int width, int height)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
|
||||
|
||||
gtk_widget_set_size_request(GTK_WIDGET(nsgtk_cw->drawing_area),
|
||||
width, height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
|
||||
int y = 0, height = 0, y0, y1;
|
||||
gdouble page;
|
||||
GtkAdjustment *vadj;
|
||||
|
||||
vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
|
||||
|
||||
assert(vadj);
|
||||
|
||||
g_object_get(vadj, "page-size", &page, NULL);
|
||||
|
||||
y0 = (int)(gtk_adjustment_get_value(vadj));
|
||||
y1 = y0 + page;
|
||||
|
||||
if ((y >= y0) && (y + height <= y1))
|
||||
return;
|
||||
if (y + height > y1)
|
||||
y0 = y0 + (y + height - y1);
|
||||
if (y < y0)
|
||||
y0 = y;
|
||||
gtk_adjustment_set_value(vadj, y0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
|
||||
GtkAdjustment *vadj;
|
||||
GtkAdjustment *hadj;
|
||||
gdouble page;
|
||||
|
||||
if (width != NULL) {
|
||||
hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
|
||||
g_object_get(hadj, "page-size", &page, NULL);
|
||||
*width = page;
|
||||
}
|
||||
|
||||
if (height != NULL) {
|
||||
vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
|
||||
g_object_get(vadj, "page-size", &page, NULL);
|
||||
*height = page;
|
||||
}}
|
||||
|
||||
|
||||
static void
|
||||
nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
|
||||
{
|
||||
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
|
||||
nsgtk_cw->drag_staus = ds;
|
||||
}
|
||||
|
||||
|
||||
struct core_window_callback_table nsgtk_cw_cb_table = {
|
||||
.redraw_request = nsgtk_cw_redraw_request,
|
||||
.update_size = nsgtk_cw_update_size,
|
||||
.scroll_visible = nsgtk_cw_scroll_visible,
|
||||
.get_window_dimensions = nsgtk_cw_get_window_dimensions,
|
||||
.drag_status = nsgtk_cw_drag_status
|
||||
};
|
||||
|
||||
/* exported function documented gtk/corewindow.h */
|
||||
nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw)
|
||||
{
|
||||
nsgtk_cw->cb_table = &nsgtk_cw_cb_table;
|
||||
|
||||
/* input method setup */
|
||||
nsgtk_cw->input_method = gtk_im_multicontext_new();
|
||||
gtk_im_context_set_client_window(nsgtk_cw->input_method,
|
||||
gtk_widget_get_parent_window(GTK_WIDGET(nsgtk_cw->drawing_area)));
|
||||
gtk_im_context_set_use_preedit(nsgtk_cw->input_method, FALSE);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->input_method),
|
||||
"commit",
|
||||
G_CALLBACK(nsgtk_cw_input_method_commit),
|
||||
nsgtk_cw);
|
||||
|
||||
nsgtk_connect_draw_event(GTK_WIDGET(nsgtk_cw->drawing_area),
|
||||
G_CALLBACK(nsgtk_cw_draw_event),
|
||||
nsgtk_cw);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
|
||||
"button-press-event",
|
||||
G_CALLBACK(nsgtk_cw_button_press_event),
|
||||
nsgtk_cw);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
|
||||
"button-release-event",
|
||||
G_CALLBACK(nsgtk_cw_button_release_event),
|
||||
nsgtk_cw);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
|
||||
"motion-notify-event",
|
||||
G_CALLBACK(nsgtk_cw_motion_notify_event),
|
||||
nsgtk_cw);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
|
||||
"key-press-event",
|
||||
G_CALLBACK(nsgtk_cw_keypress_event),
|
||||
nsgtk_cw);
|
||||
|
||||
g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
|
||||
"key-release-event",
|
||||
G_CALLBACK(nsgtk_cw_keyrelease_event),
|
||||
nsgtk_cw);
|
||||
|
||||
nsgtk_widget_override_background_color(
|
||||
GTK_WIDGET(nsgtk_cw->drawing_area),
|
||||
GTK_STATE_NORMAL,
|
||||
0, 0xffff, 0xffff, 0xffff);
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
nserror nsgtk_corewindow_fini(struct nsgtk_corewindow *nsgtk_cw)
|
||||
{
|
||||
g_object_unref(nsgtk_cw->input_method);
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
104
frontends/gtk/corewindow.h
Normal file
104
frontends/gtk/corewindow.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* NetSurf is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GTK_COREWINDOW_H
|
||||
#define GTK_COREWINDOW_H
|
||||
|
||||
#include "desktop/core_window.h"
|
||||
|
||||
/**
|
||||
* nsgtk core window mouse state
|
||||
*/
|
||||
struct nsgtk_corewindow_mouse {
|
||||
browser_mouse_state state; /**< last event status */
|
||||
bool pressed;
|
||||
int pressed_x;
|
||||
int pressed_y;
|
||||
int last_x;
|
||||
int last_y;
|
||||
};
|
||||
|
||||
/**
|
||||
* nsgtk core window state
|
||||
*/
|
||||
struct nsgtk_corewindow {
|
||||
/* public variables */
|
||||
/** GTK drawable widget */
|
||||
GtkDrawingArea *drawing_area;
|
||||
/** scrollable area drawing area is within */
|
||||
GtkScrolledWindow *scrolled;
|
||||
|
||||
/* private variables */
|
||||
/** Input method */
|
||||
GtkIMContext *input_method;
|
||||
/** table of callbacks for core window operations */
|
||||
struct core_window_callback_table *cb_table;
|
||||
/** mouse state */
|
||||
struct nsgtk_corewindow_mouse mouse_state;
|
||||
/** drag status set by core */
|
||||
core_window_drag_status drag_staus;
|
||||
|
||||
/**
|
||||
* callback to draw on drawable area of nsgtk core window
|
||||
*
|
||||
* \param nsgtk_cw The nsgtk core window structure.
|
||||
* \param r The rectangle of the window that needs updating.
|
||||
* \return NSERROR_OK on success otherwise apropriate error code
|
||||
*/
|
||||
nserror (*draw)(struct nsgtk_corewindow *nsgtk_cw, struct rect *r);
|
||||
|
||||
/**
|
||||
* callback for keypress on nsgtk core window
|
||||
*
|
||||
* \param nsgtk_cw The nsgtk core window structure.
|
||||
* \param nskey The netsurf key code.
|
||||
* \return NSERROR_OK if key processed,
|
||||
* NSERROR_NOT_IMPLEMENTED if key not processed
|
||||
* otherwise apropriate error code
|
||||
*/
|
||||
nserror (*key)(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey);
|
||||
|
||||
/**
|
||||
* callback for mouse event on nsgtk core window
|
||||
*
|
||||
* \param nsgtk_cw The nsgtk core window structure.
|
||||
* \param mouse_state mouse state
|
||||
* \param x location of event
|
||||
* \param y location of event
|
||||
* \return NSERROR_OK on sucess otherwise apropriate error code.
|
||||
*/
|
||||
nserror (*mouse)(struct nsgtk_corewindow *nsgtk_cw, browser_mouse_state mouse_state, int x, int y);
|
||||
};
|
||||
|
||||
/**
|
||||
* initialise elements of gtk core window.
|
||||
*
|
||||
* \param nsgtk_cw A gtk core window structure to initialise
|
||||
* \return NSERROR_OK on successful initialisation otherwise error code.
|
||||
*/
|
||||
nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw);
|
||||
|
||||
/**
|
||||
* finalise elements of gtk core window.
|
||||
*
|
||||
* \param nsgtk_cw A gtk core window structure to initialise
|
||||
* \return NSERROR_OK on successful finalisation otherwise error code.
|
||||
*/
|
||||
nserror nsgtk_corewindow_fini(struct nsgtk_corewindow *nsgtk_cw);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user