You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
netsurf/frontends/qt/widget.cpp

347 lines
7.1 KiB

/*
* Copyright 2023 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
* Widget methods for browsing context display.
*/
#include <QPaintEvent>
#include <QPainter>
extern "C" {
#include "utils/errors.h"
#include "utils/nsoption.h"
#include "netsurf/plotters.h"
#include "netsurf/keypress.h"
}
#include "qt/widget.cls.h"
#include "qt/plotters.h"
#include "qt/keymap.h"
/**
* netsurf widget class constructor
*/
NS_Widget::NS_Widget(QWidget *parent, struct browser_window *bw)
: QWidget(parent, Qt::Widget),
m_bw(bw),
m_xoffset(0),
m_yoffset(0)
{
pointer_shape = GUI_POINTER_DEFAULT;
setFocusPolicy(Qt::StrongFocus);
setMouseTracking(true);
}
/**
* widget has been resized
*/
void NS_Widget::resizeEvent(QResizeEvent *event)
{
browser_window_schedule_reformat(m_bw);
}
/**
* redraw the netsurf browsing widget
*/
void NS_Widget::paintEvent(QPaintEvent *event)
{
struct rect clip;
QPainter *painter;
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &nsqt_plotters,
.priv = NULL,
};
/* netsurf render clip region coordinates */
clip.x0 = event->rect().left();
clip.y0 = event->rect().top();
clip.x1 = clip.x0 + event->rect().width();
clip.y1 = clip.y0 + event->rect().height();
painter = new QPainter(this);
ctx.priv = painter;
browser_window_redraw(m_bw,
- m_xoffset,
- m_yoffset,
&clip,
&ctx);
delete painter;
}
void NS_Widget::mouseMoveEvent(QMouseEvent *event)
{
const QPointF pos = event->position();
int bms = BROWSER_MOUSE_HOVER; /* empty state */
browser_window_mouse_track(m_bw,
(browser_mouse_state)bms,
pos.x() + m_xoffset,
pos.y() + m_yoffset);
}
void NS_Widget::mousePressEvent(QMouseEvent *event)
{
int bms = BROWSER_MOUSE_HOVER; /* empty state */
const QPointF pos = event->position();
Qt::MouseButton button = event->button();
Qt::KeyboardModifiers mods = event->modifiers();
/* pressed buttons */
if ((button & Qt::LeftButton) != 0) {
bms |= BROWSER_MOUSE_PRESS_1;
}
if ((button & Qt::MiddleButton) != 0) {
bms |= BROWSER_MOUSE_PRESS_2;
}
if ((button & Qt::RightButton) != 0) {
bms |= BROWSER_MOUSE_PRESS_3;
}
if ((button & Qt::BackButton) != 0) {
bms |= BROWSER_MOUSE_PRESS_4;
}
if ((button & Qt::ForwardButton) != 0) {
bms |= BROWSER_MOUSE_PRESS_5;
}
/* keyboard modifiers */
if ((mods & Qt::ShiftModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_1;
}
if ((mods & Qt::ControlModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_2;
}
if ((mods & Qt::AltModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_3;
}
if ((mods & Qt::MetaModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_4;
}
browser_window_mouse_click(m_bw,
(browser_mouse_state)bms,
pos.x() + m_xoffset,
pos.y() + m_yoffset);
}
void NS_Widget::mouseReleaseEvent(QMouseEvent *event)
{
int bms = BROWSER_MOUSE_HOVER; /* empty state */
const QPointF pos = event->position();
Qt::MouseButton button = event->button();
Qt::KeyboardModifiers mods = event->modifiers();
/* released buttons */
if ((button & Qt::LeftButton) != 0) {
bms |= BROWSER_MOUSE_CLICK_1;
}
if ((button & Qt::MiddleButton) != 0) {
bms |= BROWSER_MOUSE_CLICK_2;
}
if ((button & Qt::RightButton) != 0) {
bms |= BROWSER_MOUSE_CLICK_3;
}
if ((button & Qt::BackButton) != 0) {
bms |= BROWSER_MOUSE_CLICK_4;
}
if ((button & Qt::ForwardButton) != 0) {
bms |= BROWSER_MOUSE_CLICK_5;
}
/* keyboard modifiers */
if ((mods & Qt::ShiftModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_1;
}
if ((mods & Qt::ControlModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_2;
}
if ((mods & Qt::AltModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_3;
}
if ((mods & Qt::MetaModifier) != 0) {
bms |= BROWSER_MOUSE_MOD_4;
}
browser_window_mouse_click(m_bw,
(browser_mouse_state)bms,
pos.x() + m_xoffset,
pos.y() + m_yoffset);
}
void NS_Widget::keyPressEvent(QKeyEvent *event)
{
uint32_t nskey;
nskey = qkeyevent_to_nskey(event);
if (browser_window_key_press(m_bw, nskey) == false) {
QWidget::keyPressEvent(event);
}
}
/**
* get the current scroll offsets
*/
bool NS_Widget::get_scroll(int *sx, int *sy)
{
*sx = m_xoffset;
*sy = m_yoffset;
return true;
}
/**
* get the viewable dimensions of browsing context
*/
nserror NS_Widget::get_dimensions(int *width, int *height)
{
*width = size().width();
*height = size().height();
return NSERROR_OK;
}
/**
* change pointer
*/
void NS_Widget::set_pointer(enum gui_pointer_shape set_shape)
{
enum Qt::CursorShape qshape = Qt::ArrowCursor;
/* if the shape is being changed to what is already set there is
* nothing to do.
*/
if (pointer_shape == set_shape) {
return;
}
pointer_shape = set_shape;
switch (pointer_shape) {
case GUI_POINTER_POINT:
qshape = Qt::PointingHandCursor;
break;
case GUI_POINTER_CARET:
qshape = Qt::IBeamCursor;
break;
case GUI_POINTER_CROSS:
qshape = Qt::CrossCursor;
break;
case GUI_POINTER_MOVE:
qshape = Qt::OpenHandCursor;
break;
case GUI_POINTER_NOT_ALLOWED:
case GUI_POINTER_NO_DROP:
qshape = Qt::ForbiddenCursor;
break;
case GUI_POINTER_WAIT:
qshape = Qt::WaitCursor;
break;
case GUI_POINTER_HELP:
qshape = Qt::WhatsThisCursor;
break;
case GUI_POINTER_UP:
case GUI_POINTER_DOWN:
qshape = Qt::SizeVerCursor;
break;
case GUI_POINTER_LEFT:
case GUI_POINTER_RIGHT:
qshape = Qt::SizeHorCursor;
break;
case GUI_POINTER_RU:
case GUI_POINTER_LD:
qshape = Qt::SizeBDiagCursor;
break;
case GUI_POINTER_LU:
case GUI_POINTER_RD:
qshape = Qt::SizeFDiagCursor;
break;
case GUI_POINTER_PROGRESS:
qshape = Qt::BusyCursor;
break;
case GUI_POINTER_MENU:
case GUI_POINTER_DEFAULT:
default:
qshape = Qt::ArrowCursor;
break;
}
setCursor(QCursor(qshape));
}
/**
* mark an area of the browsing context as invalid
*/
nserror NS_Widget::invalidate(const struct rect *rect)
{
if (rect == NULL) {
update();
} else {
update(rect->x0,
rect->y0,
rect->x1 - rect->x0,
rect->y1 - rect->y0);
}
return NSERROR_OK;
}
/**
* slot to recive horizontal scroll signal
*/
void NS_Widget::setHorizontalScroll(int value)
{
m_xoffset = value;
update();
}
/**
* slot to recive vertical scroll signal
*/
void NS_Widget::setVerticalScroll(int value)
{
m_yoffset = value;
update();
}
QSize NS_Widget::sizeHint() const
{
int width = nsoption_int(window_width);
if (width == 0) {
width = 1000;
}
int height = nsoption_int(window_height);
if (height == 0) {
height = 700;
}
QSize s(width, height);
return s;
}