mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-30 02:03:14 +03:00
c105738fa3
This changes the LOG macro to be varadic removing the need for all callsites to have double bracketing and allows for future improvement on how we use the logging macros. The callsites were changed with coccinelle and the changes checked by hand. Compile tested for several frontends but not all. A formatting annotation has also been added which allows the compiler to check the parameters and types passed to the logging.
1541 lines
46 KiB
C
1541 lines
46 KiB
C
/*
|
|
* Copyright 2010 Ole Loots <ole@monochrom.net>
|
|
*
|
|
* 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/>.
|
|
*
|
|
* Module Description:
|
|
*
|
|
* This File implements the NetSurf Browser window, or passed functionality to
|
|
* the appropriate widget's.
|
|
*
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <osbind.h>
|
|
|
|
#include <mt_gem.h>
|
|
|
|
#include "utils/log.h"
|
|
#include "desktop/browser.h"
|
|
#include "desktop/mouse.h"
|
|
#include "desktop/plotters.h"
|
|
#include "desktop/textinput.h"
|
|
#include "content/content.h"
|
|
#include "content/hlcache.h"
|
|
#include "content/urldb.h"
|
|
|
|
#include "atari/res/netsurf.rsh"
|
|
#include "atari/gemtk/gemtk.h"
|
|
#include "atari/ctxmenu.h"
|
|
#include "atari/gui.h"
|
|
#include "atari/rootwin.h"
|
|
#include "atari/misc.h"
|
|
#include "atari/plot/plot.h"
|
|
#include "atari/toolbar.h"
|
|
#include "atari/statusbar.h"
|
|
#include "atari/search.h"
|
|
#include "atari/osspec.h"
|
|
#include "atari/encoding.h"
|
|
#include "atari/redrawslots.h"
|
|
#include "atari/toolbar.h"
|
|
#include "atari/findfile.h"
|
|
#include "atari/bitmap.h"
|
|
|
|
extern struct gui_window *input_window;
|
|
extern EVMULT_OUT aes_event_out;
|
|
extern GRECT desk_area;
|
|
|
|
struct rootwin_data_s {
|
|
struct s_gui_win_root *rootwin;
|
|
};
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Static module event handlers */
|
|
/* -------------------------------------------------------------------------- */
|
|
static void on_redraw(ROOTWIN *rootwin, short msg[8]);
|
|
static void on_resized(ROOTWIN *rootwin);
|
|
static void on_file_dropped(ROOTWIN *rootwin, short msg[8]);
|
|
static short on_window_key_input(ROOTWIN * rootwin, unsigned short nkc);
|
|
static void on_content_mouse_click(ROOTWIN *rootwin);
|
|
static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area);
|
|
static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip);
|
|
|
|
bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
|
|
|
|
static bool redraw_active = false;
|
|
|
|
static const struct redraw_context rootwin_rdrw_ctx = {
|
|
.interactive = true,
|
|
.background_images = true,
|
|
.plot = &atari_plotters
|
|
};
|
|
|
|
static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
|
|
{
|
|
short retval = 0;
|
|
GRECT area;
|
|
static bool prev_url = false;
|
|
struct rootwin_data_s * data = gemtk_wm_get_user_data(win);
|
|
struct gui_window *tmp;
|
|
|
|
|
|
if ((ev_out->emo_events & MU_MESAG) != 0) {
|
|
// handle message
|
|
//printf("root win msg: %d\n", msg[0]);
|
|
switch (msg[0]) {
|
|
|
|
case WM_REDRAW:
|
|
LOG("WM_REDRAW");
|
|
on_redraw(data->rootwin, msg);
|
|
break;
|
|
|
|
case WM_REPOSED:
|
|
case WM_SIZED:
|
|
case WM_MOVED:
|
|
case WM_FULLED:
|
|
LOG("WM_SIZED");
|
|
on_resized(data->rootwin);
|
|
break;
|
|
|
|
case WM_ICONIFY:
|
|
// TODO: find next active gui window and schedule redraw for that.
|
|
tmp = window_list;
|
|
while(tmp != NULL){
|
|
if(tmp->root != data->rootwin){
|
|
gemtk_wm_send_msg(tmp->root->win, WM_TOPPED, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
tmp = tmp->next;
|
|
}
|
|
break;
|
|
|
|
case WM_TOPPED:
|
|
case WM_NEWTOP:
|
|
case WM_UNICONIFY:
|
|
LOG("WM_TOPPED");
|
|
gui_set_input_gui_window(data->rootwin->active_gui_window);
|
|
//window_restore_active_gui_window(data->rootwin);
|
|
// TODO: use something like "restore_active_gui_window_state()"
|
|
|
|
break;
|
|
|
|
case WM_CLOSED:
|
|
// TODO: this needs to iterate through all gui windows and
|
|
// check if the rootwin is this window...
|
|
if (data->rootwin->active_gui_window != NULL) {
|
|
LOG("WM_CLOSED initiated destroy for bw %p", data->rootwin->active_gui_window->browser->bw);
|
|
browser_window_destroy(
|
|
data->rootwin->active_gui_window->browser->bw);
|
|
}
|
|
break;
|
|
|
|
case AP_DRAGDROP:
|
|
on_file_dropped(data->rootwin, msg);
|
|
break;
|
|
|
|
case WM_TOOLBAR:
|
|
toolbar_mouse_input(data->rootwin->toolbar, msg[4], msg[7]);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ((ev_out->emo_events & MU_KEYBD) != 0) {
|
|
|
|
// handle key
|
|
uint16_t nkc = gem_to_norm( (short)ev_out->emo_kmeta,
|
|
(short)ev_out->emo_kreturn);
|
|
LOG("rootwin MU_KEYBD input, nkc: %x\n", nkc);
|
|
retval = on_window_key_input(data->rootwin, nkc);
|
|
// printf("on_window_key_input: %d\n", retval);
|
|
|
|
}
|
|
if ((ev_out->emo_events & MU_BUTTON) != 0) {
|
|
LOG("rootwin MU_BUTTON input, x: %d, y: %d\n", ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_x);
|
|
window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
|
|
&area);
|
|
if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
|
|
area)) {
|
|
on_content_mouse_click(data->rootwin);
|
|
}
|
|
}
|
|
if ((ev_out->emo_events & (MU_M1)) != 0) {
|
|
|
|
short ghandle = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
|
|
|
|
if (data->rootwin->aes_handle==ghandle) {
|
|
// The window found at x,y is an gui_window
|
|
// and it's the input window.
|
|
window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
|
|
&area);
|
|
if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
|
|
area)) {
|
|
on_content_mouse_move(data->rootwin, &area);
|
|
} else {
|
|
GRECT tb_area;
|
|
window_get_grect(data->rootwin, BROWSER_AREA_URL_INPUT, &tb_area);
|
|
if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
|
|
tb_area)) {
|
|
gem_set_cursor(&gem_cursors.ibeam);
|
|
prev_url = true;
|
|
} else {
|
|
if(prev_url) {
|
|
struct gui_window *gw;
|
|
gw = window_get_active_gui_window(data->rootwin);
|
|
gem_set_cursor(gw->cursor);
|
|
prev_url = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(retval);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Module public functions: */
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
int window_create(struct gui_window * gw,
|
|
struct browser_window * bw,
|
|
struct gui_window * existing,
|
|
unsigned long inflags)
|
|
{
|
|
int err = 0;
|
|
bool tb, sb;
|
|
int flags;
|
|
struct rootwin_data_s *data;
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
|
|
tb = (inflags & WIDGET_TOOLBAR);
|
|
sb = (inflags & WIDGET_STATUSBAR);
|
|
|
|
flags = CLOSER | MOVER | NAME | FULLER | SMALLER;
|
|
if( inflags & WIDGET_SCROLL ) {
|
|
flags |= (UPARROW | DNARROW | LFARROW | RTARROW | VSLIDE | HSLIDE);
|
|
}
|
|
if( inflags & WIDGET_RESIZE ) {
|
|
flags |= ( SIZER );
|
|
}
|
|
if( inflags & WIDGET_STATUSBAR ) {
|
|
flags |= ( INFO );
|
|
}
|
|
|
|
gw->root = malloc(sizeof(struct s_gui_win_root));
|
|
if (gw->root == NULL)
|
|
return(-1);
|
|
memset(gw->root, 0, sizeof(struct s_gui_win_root) );
|
|
gw->root->title = malloc(atari_sysinfo.aes_max_win_title_len+1);
|
|
|
|
redraw_slots_init(&gw->root->redraw_slots, 8);
|
|
|
|
gw->root->aes_handle = wind_create(flags, 40, 40, desk_area.g_w,
|
|
desk_area.g_h);
|
|
if(gw->root->aes_handle<0) {
|
|
free(gw->root->title);
|
|
free(gw->root);
|
|
return( -1 );
|
|
}
|
|
gw->root->win = gemtk_wm_add(gw->root->aes_handle,
|
|
GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM, handle_event);
|
|
|
|
data = malloc(sizeof(struct rootwin_data_s));
|
|
data->rootwin = gw->root;
|
|
gemtk_wm_set_user_data(gw->root->win, (void*)data);
|
|
slid = gemtk_wm_get_scroll_info(gw->root->win);
|
|
slid->y_unit_px = 32;
|
|
slid->x_unit_px = 32;
|
|
|
|
/* create */
|
|
if(tb) {
|
|
gw->root->toolbar = toolbar_create(gw->root);
|
|
assert(gw->root->toolbar);
|
|
gemtk_wm_set_toolbar(gw->root->win, gw->root->toolbar->form, 0, 0);
|
|
gemtk_wm_set_toolbar_redraw_func(gw->root->win, toolbar_redraw_cb);
|
|
} else {
|
|
gw->root->toolbar = NULL;
|
|
}
|
|
|
|
/* create browser component: */
|
|
gw->browser = (struct s_browser *)malloc( sizeof(struct s_browser));
|
|
|
|
assert(gw->browser);
|
|
|
|
gw->browser->bw = bw;
|
|
gw->scale = browser_window_get_scale(bw);
|
|
|
|
|
|
/* create statusbar component: */
|
|
if(sb) {
|
|
gw->root->statusbar = sb_create( gw );
|
|
} else {
|
|
gw->root->statusbar = NULL;
|
|
}
|
|
|
|
// Setup some window defaults:
|
|
wind_set_str(gw->root->aes_handle, WF_NAME, (char*)"NetSurf");
|
|
wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_FULLREDRAW, 0, 0);
|
|
wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITW, 0, 0);
|
|
wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITH, 0, 0);
|
|
|
|
if (inflags & WIN_TOP) {
|
|
window_set_focus(gw->root, BROWSER, gw->browser);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
|
|
{
|
|
struct gui_window *w;
|
|
input_window = NULL;
|
|
|
|
LOG("window: %p, gui_window: %p", rootwin, gw);
|
|
|
|
w = window_list;
|
|
// find the next active tab:
|
|
while( w != NULL ) {
|
|
if(w->root == rootwin && w != gw) {
|
|
LOG("activating next tab %p", w);
|
|
gui_set_input_gui_window(w);
|
|
break;
|
|
}
|
|
w = w->next;
|
|
}
|
|
if(input_window == NULL) {
|
|
// the last gui window for this rootwin was removed:
|
|
redraw_slots_free(&rootwin->redraw_slots);
|
|
window_destroy(rootwin);
|
|
}
|
|
}
|
|
|
|
int window_destroy(ROOTWIN *rootwin)
|
|
{
|
|
int err = 0;
|
|
struct gui_window *w;
|
|
|
|
assert(rootwin != NULL);
|
|
|
|
LOG("%p", rootwin);
|
|
|
|
if (gemtk_wm_get_user_data(rootwin->win) != NULL) {
|
|
free(gemtk_wm_get_user_data(rootwin->win));
|
|
}
|
|
|
|
// make sure we do not destroy windows which have gui_windows attached:
|
|
w = window_list;
|
|
while( w != NULL ) {
|
|
if(w->root == rootwin) {
|
|
assert(rootwin == NULL);
|
|
}
|
|
w = w->next;
|
|
}
|
|
|
|
if (rootwin->toolbar)
|
|
toolbar_destroy(rootwin->toolbar);
|
|
|
|
if(rootwin->statusbar)
|
|
sb_destroy(rootwin->statusbar);
|
|
|
|
if(rootwin->title)
|
|
free(rootwin->title);
|
|
|
|
gemtk_wm_remove(rootwin->win);
|
|
wind_close(rootwin->aes_handle);
|
|
wind_delete(rootwin->aes_handle);
|
|
free(rootwin);
|
|
return(err);
|
|
}
|
|
|
|
|
|
void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos)
|
|
{
|
|
GRECT g;
|
|
|
|
rootwin->active_gui_window = gw;
|
|
|
|
assert(rootwin->active_gui_window != NULL);
|
|
|
|
wind_open(rootwin->aes_handle, pos.g_x, pos.g_y, pos.g_w, pos.g_h );
|
|
wind_set_str(rootwin->aes_handle, WF_NAME, (char *)"");
|
|
|
|
rootwin->active_gui_window->browser->attached = true;
|
|
if(rootwin->statusbar != NULL) {
|
|
sb_attach(rootwin->statusbar, rootwin->active_gui_window);
|
|
}
|
|
|
|
/* Set initial size of the toolbar region: */
|
|
gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, &g);
|
|
toolbar_set_attached(rootwin->toolbar, true);
|
|
toolbar_set_dimensions(rootwin->toolbar, &g);
|
|
|
|
/* initially hide the search area of the toolbar: */
|
|
window_close_search(rootwin);
|
|
|
|
window_update_back_forward(rootwin);
|
|
|
|
window_set_focus(rootwin, BROWSER, rootwin->active_gui_window->browser);
|
|
}
|
|
|
|
void window_restore_active_gui_window(ROOTWIN *rootwin)
|
|
{
|
|
GRECT tb_area;
|
|
struct gui_window *gw;
|
|
|
|
LOG("");
|
|
|
|
assert(rootwin->active_gui_window);
|
|
|
|
gw = rootwin->active_gui_window;
|
|
|
|
window_set_icon(rootwin, gw->icon);
|
|
window_set_stauts(rootwin, gw->status);
|
|
window_set_title(rootwin, gw->title);
|
|
|
|
if (gw->search != NULL) {
|
|
// TODO: update search session (especially browser window)
|
|
}
|
|
|
|
toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
|
|
gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
|
|
|
|
window_update_back_forward(rootwin);
|
|
|
|
toolbar_set_url(rootwin->toolbar, gw->url);
|
|
}
|
|
|
|
|
|
/* update back forward buttons (see tb_update_buttons (bug) ) */
|
|
void window_update_back_forward(struct s_gui_win_root *rootwin)
|
|
{
|
|
struct gui_window * active_gw = rootwin->active_gui_window;
|
|
toolbar_update_buttons(rootwin->toolbar, active_gw->browser->bw, -1);
|
|
}
|
|
|
|
void window_set_stauts(struct s_gui_win_root *rootwin, char * text)
|
|
{
|
|
assert(rootwin != NULL);
|
|
|
|
CMP_STATUSBAR sb = rootwin->statusbar;
|
|
|
|
if( sb == NULL)
|
|
return;
|
|
|
|
if(text != NULL)
|
|
sb_set_text(sb, text);
|
|
else
|
|
sb_set_text(sb, "");
|
|
}
|
|
|
|
void window_set_title(struct s_gui_win_root * rootwin, char *title)
|
|
{
|
|
wind_set_str(rootwin->aes_handle, WF_NAME, title);
|
|
}
|
|
|
|
void window_scroll_by(ROOTWIN *root, int sx, int sy)
|
|
{
|
|
struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(root->win);
|
|
|
|
if (sx < 0) {
|
|
sx = 0;
|
|
}
|
|
if (sy < 0) {
|
|
sy = 0;
|
|
}
|
|
int xunits = sx / slid->x_unit_px;
|
|
int yunits = sy / slid->y_unit_px;
|
|
|
|
gemtk_wm_scroll(root->win, GEMTK_WM_VSLIDER, yunits - slid->y_pos, false);
|
|
gemtk_wm_scroll(root->win, GEMTK_WM_HSLIDER, xunits - slid->x_pos, false);
|
|
gemtk_wm_update_slider(root->win, GEMTK_WM_VH_SLIDER);
|
|
}
|
|
|
|
/**
|
|
* Set the dimensions of the scrollable content.
|
|
*
|
|
*/
|
|
void window_set_content_size(ROOTWIN *rootwin, int width, int height)
|
|
{
|
|
GRECT area;
|
|
struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
|
|
|
|
slid->x_units = (width/slid->x_unit_px);
|
|
slid->y_units = (height/slid->y_unit_px);
|
|
if(slid->x_units < slid->x_pos)
|
|
slid->x_pos = 0;
|
|
if(slid->y_units < slid->y_pos)
|
|
slid->y_pos = 0;
|
|
gemtk_wm_update_slider(rootwin->win, GEMTK_WM_VH_SLIDER);
|
|
}
|
|
|
|
/* set focus to an arbitary element */
|
|
void window_set_focus(struct s_gui_win_root *rootwin,
|
|
enum focus_element_type type, void * element)
|
|
{
|
|
assert(rootwin != NULL);
|
|
|
|
if (rootwin->focus.type != type || rootwin->focus.element != element) {
|
|
LOG("Set focus: %p (%d)\n", element, type);
|
|
rootwin->focus.type = type;
|
|
rootwin->focus.element = element;
|
|
switch( type ) {
|
|
|
|
case URL_WIDGET:
|
|
// TODO: make something like: toolbar_text_select_all();
|
|
toolbar_key_input(rootwin->toolbar, (short)(NKF_CTRL | 'A') );
|
|
/*
|
|
ta = toolbar_get_textarea(rootwin->toolbar,
|
|
URL_INPUT_TEXT_AREA);
|
|
textarea_keypress(ta, NS_KEY_SELECT_ALL);
|
|
*/
|
|
break;
|
|
|
|
case SEARCH_INPUT:
|
|
gemtk_wm_set_toolbar_edit_obj(rootwin->win, TOOLBAR_TB_SRCH, 0);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check if the url widget has focus */
|
|
bool window_url_widget_has_focus(struct s_gui_win_root *rootwin)
|
|
{
|
|
assert(rootwin != NULL);
|
|
|
|
if (rootwin->focus.type == URL_WIDGET) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* check if an arbitary window widget / or frame has the focus */
|
|
bool window_widget_has_focus(struct s_gui_win_root *rootwin,
|
|
enum focus_element_type t, void * element)
|
|
{
|
|
assert(rootwin != NULL);
|
|
if( element == NULL ) {
|
|
return((rootwin->focus.type == t));
|
|
}
|
|
|
|
return((element == rootwin->focus.element && t == rootwin->focus.type));
|
|
}
|
|
|
|
void window_set_icon(ROOTWIN *rootwin, struct bitmap * bmp )
|
|
{
|
|
rootwin->icon = bmp;
|
|
/* redraw window when it is iconyfied: */
|
|
if (rootwin->icon != NULL) {
|
|
if (gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
|
|
window_redraw_favicon(rootwin, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
|
|
{
|
|
struct gui_window *old_gw = rootwin->active_gui_window;
|
|
|
|
LOG("");
|
|
|
|
if (rootwin->active_gui_window != NULL) {
|
|
if(rootwin->active_gui_window == gw) {
|
|
LOG("nothing to do...");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// TODO: when the window isn't on top, initiate WM_TOPPED.
|
|
|
|
rootwin->active_gui_window = gw;
|
|
if (old_gw != NULL) {
|
|
LOG("restoring window...");
|
|
window_restore_active_gui_window(rootwin);
|
|
}
|
|
}
|
|
|
|
struct gui_window * window_get_active_gui_window(ROOTWIN * rootwin)
|
|
{
|
|
return(rootwin->active_gui_window);
|
|
}
|
|
|
|
void window_get_scroll(ROOTWIN *rootwin, int *x, int *y)
|
|
{
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
|
|
slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
|
|
*x = slid->x_pos * slid->x_unit_px;
|
|
*y = slid->y_pos * slid->y_unit_px;
|
|
}
|
|
|
|
void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d)
|
|
{
|
|
|
|
d->g_x = 0;
|
|
d->g_y = 0;
|
|
d->g_w = 0;
|
|
d->g_h = 0;
|
|
|
|
if (which == BROWSER_AREA_TOOLBAR) {
|
|
// gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, d);
|
|
toolbar_get_grect(rootwin->toolbar, 0, d);
|
|
|
|
} else if (which == BROWSER_AREA_CONTENT) {
|
|
|
|
GRECT tb_area;
|
|
|
|
gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, d);
|
|
toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
|
|
|
|
d->g_y += tb_area.g_h;
|
|
d->g_h -= tb_area.g_h;
|
|
|
|
} else if (which == BROWSER_AREA_URL_INPUT) {
|
|
|
|
toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_URL, d);
|
|
|
|
} else if (which == BROWSER_AREA_SEARCH) {
|
|
// todo: check if search is visible
|
|
toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_SEARCH, d);
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
// sanitize the results
|
|
if (d->g_h < 0) {
|
|
d->g_h = 0;
|
|
}
|
|
if (d->g_w < 0) {
|
|
d->g_w = 0;
|
|
}
|
|
|
|
//printf("window_get_grect %d:", which);
|
|
//dbg_grect("", d);
|
|
|
|
}
|
|
|
|
|
|
void window_open_search(ROOTWIN *rootwin, bool reformat)
|
|
{
|
|
struct browser_window *bw;
|
|
struct gui_window *gw;
|
|
GRECT area;
|
|
OBJECT *obj;
|
|
|
|
LOG("");
|
|
|
|
gw = rootwin->active_gui_window;
|
|
bw = gw->browser->bw;
|
|
obj = toolbar_get_form(rootwin->toolbar);
|
|
|
|
if (gw->search == NULL) {
|
|
gw->search = nsatari_search_session_create(obj, gw);
|
|
}
|
|
|
|
toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, true);
|
|
window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
|
|
gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
|
|
window_get_grect(rootwin, BROWSER_AREA_SEARCH, &area);
|
|
window_schedule_redraw_grect(rootwin, &area);
|
|
window_process_redraws(rootwin);
|
|
window_set_focus(rootwin, SEARCH_INPUT, NULL);
|
|
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
|
|
if (reformat) {
|
|
browser_window_reformat(bw, false, area.g_w, area.g_h);
|
|
}
|
|
}
|
|
|
|
void window_close_search(ROOTWIN *rootwin)
|
|
{
|
|
struct browser_window *bw;
|
|
struct gui_window *gw;
|
|
GRECT area;
|
|
OBJECT *obj;
|
|
|
|
|
|
gw = rootwin->active_gui_window;
|
|
bw = gw->browser->bw;
|
|
obj = gemtk_obj_get_tree(TOOLBAR);
|
|
|
|
if (gw->search != NULL) {
|
|
nsatari_search_session_destroy(gw->search);
|
|
gw->search = NULL;
|
|
}
|
|
|
|
toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, false);
|
|
window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
|
|
gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
|
|
browser_window_reformat(bw, false, area.g_w, area.g_h);
|
|
}
|
|
|
|
/**
|
|
* Redraw the favicon
|
|
*/
|
|
void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
|
|
{
|
|
GRECT work, visible, clip;
|
|
|
|
assert(rootwin);
|
|
|
|
//printf("window_redraw_favicon: root: %p, win: %p\n", rootwin, rootwin->win);
|
|
|
|
gemtk_wm_clear(rootwin->win);
|
|
gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
|
|
|
|
if (clip_ro == NULL) {
|
|
clip = work;
|
|
} else {
|
|
clip = *clip_ro;
|
|
if(!rc_intersect(&work, &clip)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//dbg_grect("favicon redrw area", clip);
|
|
//dbg_grect("favicon work area", &work);
|
|
|
|
if (rootwin->icon == NULL) {
|
|
//printf("window_redraw_favicon OBJCTREE\n");
|
|
|
|
OBJECT * tree = gemtk_obj_get_tree(ICONIFY);
|
|
tree->ob_x = work.g_x;
|
|
tree->ob_y = work.g_y;
|
|
tree->ob_width = work.g_w;
|
|
tree->ob_height = work.g_h;
|
|
|
|
wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
|
|
while (visible.g_h > 0 && visible.g_w > 0) {
|
|
|
|
if (rc_intersect(&clip, &visible)) {
|
|
//dbg_grect("redraw vis area", &visible);
|
|
objc_draw(tree, 0, 8, visible.g_x, visible.g_y, visible.g_w,
|
|
visible.g_h);
|
|
} else {
|
|
//dbg_grect("redraw vis area outside", &visible);
|
|
}
|
|
|
|
wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
|
|
}
|
|
|
|
} else {
|
|
//printf("window_redraw_favicon image %p\n", rootwin->icon);
|
|
VdiHdl plot_vdi_handle = plot_get_vdi_handle();
|
|
short pxy[4];
|
|
int xoff=0;
|
|
|
|
if (work.g_w > work.g_h) {
|
|
xoff = ((work.g_w-work.g_h)/2);
|
|
work.g_w = work.g_h;
|
|
}
|
|
plot_set_dimensions( work.g_x+xoff, work.g_y, work.g_w,
|
|
work.g_h);
|
|
|
|
wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
|
|
while (visible.g_h > 0 && visible.g_w > 0) {
|
|
|
|
if (rc_intersect(&clip, &visible)) {
|
|
|
|
//dbg_grect("redraw vis area", &visible);
|
|
|
|
// Manually clip drawing region:
|
|
pxy[0] = visible.g_x;
|
|
pxy[1] = visible.g_y;
|
|
pxy[2] = pxy[0] + visible.g_w-1;
|
|
pxy[3] = pxy[1] + visible.g_h-1;
|
|
vs_clip(plot_vdi_handle, 1, (short*)&pxy);
|
|
//dbg_pxy("vdi clip", (short*)&pxy);
|
|
|
|
atari_plotters.bitmap(0, 0, work.g_w, work.g_h,
|
|
rootwin->icon, 0xffffff, 0);
|
|
} else {
|
|
//dbg_grect("redraw vis area outside", &visible);
|
|
}
|
|
|
|
wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***
|
|
* Schedule an redraw area, redraw requests during redraw are
|
|
* not optimized (merged) into other areas, so that the redraw
|
|
* functions can spot the change.
|
|
*
|
|
*/
|
|
void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area)
|
|
{
|
|
GRECT work;
|
|
|
|
|
|
//dbg_grect("window_schedule_redraw_grect input ", area);
|
|
|
|
gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
|
|
if(!rc_intersect(area, &work))
|
|
return;
|
|
|
|
//dbg_grect("window_schedule_redraw_grect intersection ", &work);
|
|
|
|
redraw_slot_schedule_grect(&rootwin->redraw_slots, &work, redraw_active);
|
|
}
|
|
|
|
static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
|
|
GRECT *clip,
|
|
struct gemtk_wm_scroll_info_s * slid,
|
|
struct browser_window *bw)
|
|
{
|
|
|
|
struct rect redraw_area;
|
|
GRECT content_area_rel;
|
|
float oldscale = 1.0;
|
|
|
|
//dbg_grect("browser redraw, content area", content_area);
|
|
//dbg_grect("browser redraw, content clip", clip);
|
|
|
|
plot_set_dimensions(content_area->g_x, content_area->g_y,
|
|
content_area->g_w, content_area->g_h);
|
|
oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw));
|
|
|
|
/* first, we make the coords relative to the content area: */
|
|
content_area_rel.g_x = clip->g_x - content_area->g_x;
|
|
content_area_rel.g_y = clip->g_y - content_area->g_y;
|
|
content_area_rel.g_w = clip->g_w;
|
|
content_area_rel.g_h = clip->g_h;
|
|
|
|
if (content_area_rel.g_x < 0) {
|
|
content_area_rel.g_w += content_area_rel.g_x;
|
|
content_area_rel.g_x = 0;
|
|
}
|
|
|
|
if (content_area_rel.g_y < 0) {
|
|
content_area_rel.g_h += content_area_rel.g_y;
|
|
content_area_rel.g_y = 0;
|
|
}
|
|
|
|
//dbg_grect("browser redraw, relative plot coords:", &content_area_rel);
|
|
|
|
redraw_area.x0 = content_area_rel.g_x;
|
|
redraw_area.y0 = content_area_rel.g_y;
|
|
redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w;
|
|
redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h;
|
|
|
|
plot_clip(&redraw_area);
|
|
|
|
//dbg_rect("rdrw area", &redraw_area);
|
|
|
|
browser_window_redraw( bw, -(slid->x_pos*slid->x_unit_px),
|
|
-(slid->y_pos*slid->y_unit_px), &redraw_area, &rootwin_rdrw_ctx);
|
|
|
|
plot_set_scale(oldscale);
|
|
}
|
|
|
|
|
|
void window_place_caret(ROOTWIN *rootwin, short mode, int content_x,
|
|
int content_y, int h, GRECT *work)
|
|
{
|
|
struct s_caret *caret = &rootwin->caret;
|
|
VdiHdl vh = gemtk_wm_get_vdi_handle(rootwin->win);
|
|
short pxy[8];
|
|
GRECT mywork, caret_pos;
|
|
MFDB screen;
|
|
int scroll_x, scroll_y;
|
|
uint16_t *fd_addr;
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
short colors[2] = {G_BLACK, G_WHITE};
|
|
bool render_required = false;
|
|
|
|
// avoid duplicate draw of the caret:
|
|
if (mode == 1 &&(caret->state&CARET_STATE_VISIBLE)!=0) {
|
|
if (caret->dimensions.g_x == content_x
|
|
&& caret->dimensions.g_y == content_y
|
|
&& caret->dimensions.g_h == h) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(work == NULL) {
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &mywork);
|
|
work = &mywork;
|
|
}
|
|
slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
|
|
scroll_x = slid->x_pos * slid->x_unit_px;
|
|
scroll_y = slid->y_pos * slid->y_unit_px;
|
|
|
|
init_mfdb(0, 1, h, 0, &screen);
|
|
|
|
// enable clipping:
|
|
pxy[0] = work->g_x;
|
|
pxy[1] = work->g_y;
|
|
pxy[2] = pxy[0] + work->g_w - 1;
|
|
pxy[3] = pxy[1] + work->g_h - 1;
|
|
vs_clip(vh, 1, pxy);
|
|
|
|
// when the caret is visible, undraw it:
|
|
if (caret->symbol.fd_addr != NULL
|
|
&& (caret->state&CARET_STATE_VISIBLE)!=0) {
|
|
|
|
caret_pos.g_x = work->g_x + (caret->dimensions.g_x - scroll_x);
|
|
caret_pos.g_y = work->g_y + (caret->dimensions.g_y - scroll_y);
|
|
caret_pos.g_w = caret->dimensions.g_w;
|
|
caret_pos.g_h = caret->dimensions.g_h;
|
|
|
|
if (rc_intersect(work, &caret_pos)) {
|
|
|
|
pxy[0] = 0;
|
|
pxy[1] = 0;
|
|
pxy[2] = caret->dimensions.g_w-1;
|
|
pxy[3] = caret->dimensions.g_h-1;
|
|
|
|
pxy[4] = caret_pos.g_x;
|
|
pxy[5] = caret_pos.g_y;
|
|
pxy[6] = pxy[4] + caret_pos.g_w-1;
|
|
pxy[7] = pxy[5] + caret_pos.g_h-1;
|
|
|
|
vrt_cpyfm(vh, MD_XOR, pxy, &caret->symbol, &screen, colors);
|
|
}
|
|
}
|
|
if (mode == 0) {
|
|
// update state:
|
|
caret->state &= ~CARET_STATE_VISIBLE;
|
|
goto exit;
|
|
}
|
|
|
|
// when the caret isn't allocated, create it:
|
|
if (caret->symbol.fd_addr == NULL) {
|
|
caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_ZEROMEM,
|
|
&caret->symbol);
|
|
render_required = true;
|
|
} else {
|
|
// the caret may need more memory:
|
|
if (caret->dimensions.g_h < h) {
|
|
caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_NOALLOC,
|
|
&caret->symbol);
|
|
realloc(caret->symbol.fd_addr, caret->fd_size);
|
|
render_required = true;
|
|
}
|
|
}
|
|
|
|
// set new caret position:
|
|
caret->dimensions.g_x = content_x;
|
|
caret->dimensions.g_y = content_y;
|
|
caret->dimensions.g_w = 1;
|
|
caret->dimensions.g_h = h;
|
|
|
|
// draw the caret into the mfdb buffer:
|
|
if (render_required) {
|
|
int i;
|
|
|
|
assert(caret->symbol.fd_nplanes == 1);
|
|
assert(caret->symbol.fd_w == 16);
|
|
|
|
// draw an vertical line into the mfdb buffer
|
|
fd_addr = (uint16_t*)caret->symbol.fd_addr;
|
|
for(i = 0; i<caret->symbol.fd_h; i++) {
|
|
fd_addr[i] = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
// convert content coords to screen coords:
|
|
|
|
caret_pos.g_x = work->g_x + (content_x - scroll_x);
|
|
caret_pos.g_y = work->g_y + (content_y - scroll_y);
|
|
caret_pos.g_w = caret->dimensions.g_w;
|
|
caret_pos.g_h = caret->dimensions.g_h;
|
|
|
|
if (rc_intersect(work, &caret_pos) && redraw_active == false) {
|
|
|
|
pxy[0] = 0;
|
|
pxy[1] = 0;
|
|
pxy[2] = caret->dimensions.g_w-1;
|
|
pxy[3] = caret->dimensions.g_h-1;
|
|
|
|
pxy[4] = caret_pos.g_x;
|
|
pxy[5] = caret_pos.g_y;
|
|
pxy[6] = pxy[4] + caret_pos.g_w-1;
|
|
pxy[7] = pxy[5] + caret_pos.g_h-1;
|
|
|
|
//dbg_pxy("caret screen coords (md_repl)", &pxy[4]);
|
|
|
|
// TODO: walk rectangle list (use MD_REPLACE then)
|
|
// draw caret to screen coords:
|
|
vrt_cpyfm(vh, /*MD_REPLACE*/ MD_XOR, pxy, &caret->symbol, &screen, colors);
|
|
|
|
// update state:
|
|
caret->state |= CARET_STATE_VISIBLE;
|
|
}
|
|
|
|
exit:
|
|
// disable clipping:
|
|
vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy);
|
|
}
|
|
|
|
void window_process_redraws(ROOTWIN * rootwin)
|
|
{
|
|
GRECT visible_ro, tb_area, content_area;
|
|
short i;
|
|
short scroll_x=0, scroll_y=0;
|
|
bool caret_rdrw_required = false;
|
|
struct gemtk_wm_scroll_info_s *slid =NULL;
|
|
int caret_h = 0;
|
|
struct s_caret *caret = &rootwin->caret;
|
|
|
|
redraw_active = true;
|
|
|
|
window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &tb_area);
|
|
//gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
|
|
|
|
//dbg_grect("content area", &content_area);
|
|
//dbg_grect("window_process_redraws toolbar area", &tb_area);
|
|
|
|
while(plot_lock() == false);
|
|
|
|
if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)
|
|
&& rootwin->caret.dimensions.g_h > 0) {
|
|
// hide caret:
|
|
window_place_caret(rootwin, 0, -1, -1, -1, &content_area);
|
|
}
|
|
/*
|
|
short pxy_clip[4];
|
|
pxy_clip[0] = tb_area.g_x;
|
|
pxy_clip[0] = tb_area.g_y;
|
|
pxy_clip[0] = pxy_clip[0] + tb_area.g_w + content_area.g_w - 1;
|
|
pxy_clip[0] = pxy_clip[1] + tb_area.g_h + content_area.g_h - 1;
|
|
vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 1, pxy_clip);
|
|
//gemtk_wm_clear(rootwin->win);
|
|
*/
|
|
wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible_ro);
|
|
while (visible_ro.g_w > 0 && visible_ro.g_h > 0) {
|
|
plot_set_abs_clipping(&visible_ro);
|
|
|
|
//dbg_grect("visible ", &visible_ro);
|
|
|
|
// TODO: optimze the rectangle list -
|
|
// remove rectangles which were completly inside the visible area.
|
|
// that way we don't have to loop over again...
|
|
for(i=0; i<rootwin->redraw_slots.areas_used; i++) {
|
|
|
|
GRECT rdrw_area_ro = {
|
|
rootwin->redraw_slots.areas[i].x0,
|
|
rootwin->redraw_slots.areas[i].y0,
|
|
rootwin->redraw_slots.areas[i].x1 -
|
|
rootwin->redraw_slots.areas[i].x0,
|
|
rootwin->redraw_slots.areas[i].y1 -
|
|
rootwin->redraw_slots.areas[i].y0
|
|
};
|
|
|
|
if (!rc_intersect(&visible_ro, &rdrw_area_ro)) {
|
|
continue;
|
|
}
|
|
GRECT rdrw_area = rdrw_area_ro;
|
|
|
|
if (rc_intersect(&tb_area, &rdrw_area)) {
|
|
toolbar_redraw(rootwin->toolbar, &rdrw_area);
|
|
}
|
|
|
|
rdrw_area = rdrw_area_ro;
|
|
if (rc_intersect(&content_area, &rdrw_area)) {
|
|
|
|
if(slid == NULL) {
|
|
slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
|
|
scroll_x = slid->x_pos * slid->x_unit_px;
|
|
scroll_y = slid->y_pos * slid->y_unit_px;
|
|
}
|
|
|
|
window_redraw_content(rootwin, &content_area, &rdrw_area,
|
|
slid,
|
|
rootwin->active_gui_window->browser->bw);
|
|
if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
|
|
|
|
GRECT caret_pos;
|
|
|
|
caret_pos.g_x = content_area.g_x +
|
|
(caret->dimensions.g_x - scroll_x);
|
|
caret_pos.g_y = content_area.g_y +
|
|
(caret->dimensions.g_y - scroll_y);
|
|
caret_pos.g_w = caret->dimensions.g_w;
|
|
caret_pos.g_h = caret->dimensions.g_h;
|
|
|
|
if (gemtk_rc_intersect_ro(&caret_pos, &content_area)) {
|
|
caret_rdrw_required = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible_ro);
|
|
}
|
|
|
|
|
|
// disable clipping:
|
|
//vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy_clip);
|
|
|
|
if (caret_rdrw_required && ((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
|
|
|
|
// force redraw of caret:
|
|
caret_h = rootwin->caret.dimensions.g_h;
|
|
rootwin->caret.dimensions.g_h = 0;
|
|
redraw_active = false;
|
|
window_place_caret(rootwin, 1, rootwin->caret.dimensions.g_x,
|
|
rootwin->caret.dimensions.g_y,
|
|
caret_h, &content_area);
|
|
}
|
|
|
|
rootwin->redraw_slots.areas_used = 0;
|
|
redraw_active = false;
|
|
|
|
plot_unlock();
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Event Handlers: */
|
|
/* -------------------------------------------------------------------------- */
|
|
static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area)
|
|
{
|
|
int mx, my, sx, sy;
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
struct gui_window *gw;
|
|
struct browser_window *bw;
|
|
|
|
// make relative mouse coords:
|
|
mx = aes_event_out.emo_mouse.p_x - content_area->g_x;
|
|
my = aes_event_out.emo_mouse.p_y - content_area->g_y;
|
|
|
|
slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
gw = window_get_active_gui_window(rootwin);
|
|
bw = gw->browser->bw;
|
|
|
|
// calculate scroll pos. in pixel:
|
|
sx = slid->x_pos * slid->x_unit_px;
|
|
sy = slid->y_pos * slid->y_unit_px;
|
|
|
|
browser_window_mouse_track(bw, 0, mx + sx, my + sy);
|
|
}
|
|
|
|
static void on_content_mouse_click(ROOTWIN *rootwin)
|
|
{
|
|
short dummy, mbut, mx, my;
|
|
GRECT cwork;
|
|
browser_mouse_state bmstate = 0;
|
|
struct gui_window *gw;
|
|
struct gemtk_wm_scroll_info_s *slid;
|
|
|
|
gw = window_get_active_gui_window(rootwin);
|
|
if(input_window != gw) {
|
|
gui_set_input_gui_window(gw);
|
|
}
|
|
|
|
window_set_focus(gw->root, BROWSER, (void*)gw->browser );
|
|
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &cwork);
|
|
|
|
/* convert screen coords to component coords: */
|
|
mx = aes_event_out.emo_mouse.p_x - cwork.g_x;
|
|
my = aes_event_out.emo_mouse.p_y - cwork.g_y;
|
|
//printf("content click at %d,%d\n", mx, my);
|
|
|
|
/* Translate GEM key state to netsurf mouse modifier */
|
|
if ( aes_event_out.emo_kmeta & (K_RSHIFT | K_LSHIFT)) {
|
|
bmstate |= BROWSER_MOUSE_MOD_1;
|
|
} else {
|
|
bmstate &= ~(BROWSER_MOUSE_MOD_1);
|
|
}
|
|
if ( (aes_event_out.emo_kmeta & K_CTRL) ) {
|
|
bmstate |= BROWSER_MOUSE_MOD_2;
|
|
} else {
|
|
bmstate &= ~(BROWSER_MOUSE_MOD_2);
|
|
}
|
|
if ( (aes_event_out.emo_kmeta & K_ALT) ) {
|
|
bmstate |= BROWSER_MOUSE_MOD_3;
|
|
} else {
|
|
bmstate &= ~(BROWSER_MOUSE_MOD_3);
|
|
}
|
|
|
|
/* convert component coords to scrolled content coords: */
|
|
slid = gemtk_wm_get_scroll_info(rootwin->win);
|
|
int sx_origin = mx;
|
|
int sy_origin = my;
|
|
|
|
short rel_cur_x, rel_cur_y;
|
|
short prev_x=sx_origin, prev_y=sy_origin;
|
|
bool dragmode = false;
|
|
|
|
/* Detect left mouse button state and compare with event state: */
|
|
graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
|
|
if( (mbut & 1) && (aes_event_out.emo_mbutton & 1) ) {
|
|
/* Mouse still pressed, report drag */
|
|
rel_cur_x = (rel_cur_x - cwork.g_x);
|
|
rel_cur_y = (rel_cur_y - cwork.g_y);
|
|
browser_window_mouse_click( gw->browser->bw,
|
|
BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
|
|
rel_cur_x + slid->x_pos * slid->x_unit_px,
|
|
rel_cur_y + slid->y_pos * slid->y_unit_px);
|
|
do {
|
|
// only consider movements of 5px or more as drag...:
|
|
if( abs(prev_x-rel_cur_x) > 5 || abs(prev_y-rel_cur_y) > 5 ) {
|
|
browser_window_mouse_track( gw->browser->bw,
|
|
BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
|
|
rel_cur_x + slid->x_pos * slid->x_unit_px,
|
|
rel_cur_y + slid->y_pos * slid->y_unit_px);
|
|
prev_x = rel_cur_x;
|
|
prev_y = rel_cur_y;
|
|
dragmode = true;
|
|
} else {
|
|
if( dragmode == false ) {
|
|
browser_window_mouse_track( gw->browser->bw,BROWSER_MOUSE_PRESS_1,
|
|
rel_cur_x + slid->x_pos * slid->x_unit_px,
|
|
rel_cur_y + slid->y_pos * slid->y_unit_px);
|
|
}
|
|
}
|
|
|
|
// we may need to process scrolling:
|
|
// TODO: this doesn't work, because gemtk schedules redraw via
|
|
// AES window messages but we do not process them right here...
|
|
if (rootwin->redraw_slots.areas_used > 0) {
|
|
window_process_redraws(rootwin);
|
|
}
|
|
evnt_timer(150);
|
|
|
|
graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
|
|
rel_cur_x = (rel_cur_x - cwork.g_x);
|
|
rel_cur_y = (rel_cur_y - cwork.g_y);
|
|
} while( mbut & 1 );
|
|
browser_window_mouse_track(gw->browser->bw, 0,
|
|
rel_cur_x + slid->x_pos * slid->x_unit_px,
|
|
rel_cur_y + slid->y_pos * slid->y_unit_px);
|
|
} else {
|
|
/* Right button pressed? */
|
|
if ((aes_event_out.emo_mbutton & 2 ) ) {
|
|
context_popup(gw, aes_event_out.emo_mouse.p_x,
|
|
aes_event_out.emo_mouse.p_y);
|
|
} else {
|
|
browser_window_mouse_click(gw->browser->bw,
|
|
bmstate|BROWSER_MOUSE_PRESS_1,
|
|
sx_origin + slid->x_pos * slid->x_unit_px,
|
|
sy_origin + slid->y_pos * slid->y_unit_px);
|
|
browser_window_mouse_click(gw->browser->bw,
|
|
bmstate|BROWSER_MOUSE_CLICK_1,
|
|
sx_origin + slid->x_pos * slid->x_unit_px,
|
|
sy_origin + slid->y_pos * slid->y_unit_px);
|
|
}
|
|
}
|
|
if (rootwin->redraw_slots.areas_used > 0) {
|
|
window_process_redraws(rootwin);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Report keypress to browser component.
|
|
parameter:
|
|
- unsigned short nkc ( CFLIB normalised key code )
|
|
*/
|
|
static bool on_content_keypress(struct gui_window *gw, unsigned short nkc)
|
|
{
|
|
bool r = false;
|
|
unsigned char ascii = (nkc & 0xFF);
|
|
long ucs4;
|
|
long ik = nkc_to_input_key( nkc, &ucs4 );
|
|
|
|
// pass event to specific control?
|
|
|
|
if (ik == 0) {
|
|
if (ascii >= 9) {
|
|
r = browser_window_key_press(gw->browser->bw, ucs4);
|
|
}
|
|
} else {
|
|
r = browser_window_key_press(gw->browser->bw, ik);
|
|
if (r == false) {
|
|
|
|
GRECT g;
|
|
GUIWIN * w = gw->root->win;
|
|
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &g);
|
|
|
|
struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w);
|
|
|
|
switch( ik ) {
|
|
case NS_KEY_LINE_START:
|
|
gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px),
|
|
false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_LINE_END:
|
|
gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px),
|
|
false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_PAGE_UP:
|
|
gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px),
|
|
false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_PAGE_DOWN:
|
|
gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, (g.g_h/slid->y_unit_px),
|
|
false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_RIGHT:
|
|
gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -1, false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_LEFT:
|
|
gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, 1, false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_UP:
|
|
gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -1, false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_DOWN:
|
|
gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, 1, false);
|
|
r = true;
|
|
break;
|
|
|
|
case NS_KEY_TEXT_START:
|
|
window_scroll_by(gw->root, 0, 0);
|
|
r = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
gemtk_wm_update_slider(w, GEMTK_WM_VSLIDER|GEMTK_WM_HSLIDER);
|
|
}
|
|
}
|
|
|
|
return(r);
|
|
}
|
|
|
|
static short on_window_key_input(ROOTWIN *rootwin, unsigned short nkc)
|
|
{
|
|
bool done = false;
|
|
struct gui_window * gw = window_get_active_gui_window(rootwin);
|
|
|
|
if( gw == NULL )
|
|
return(false);
|
|
|
|
if(window_url_widget_has_focus((void*)gw->root)) {
|
|
/* make sure we report for the root window and report...: */
|
|
done = toolbar_key_input(gw->root->toolbar, nkc);
|
|
} else {
|
|
if( window_widget_has_focus(input_window->root, BROWSER,
|
|
(void*)input_window->browser)) {
|
|
done = on_content_keypress(input_window, nkc);
|
|
}
|
|
else if(window_widget_has_focus(input_window->root, SEARCH_INPUT, NULL)) {
|
|
OBJECT * obj;
|
|
obj = toolbar_get_form(input_window->root->toolbar);
|
|
obj[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED;
|
|
obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
|
|
window_schedule_redraw_grect(input_window->root,
|
|
gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_FWD));
|
|
window_schedule_redraw_grect(input_window->root,
|
|
gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_BACK));
|
|
}
|
|
}
|
|
return((done==true) ? 1 : 0);
|
|
}
|
|
|
|
|
|
static void on_redraw(ROOTWIN *rootwin, short msg[8])
|
|
{
|
|
GRECT clip = {msg[4], msg[5], msg[6], msg[7]};
|
|
|
|
//dbg_grect("on_redraw", &clip);
|
|
|
|
if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
|
|
// TODO: remove asignment:
|
|
window_redraw_favicon(rootwin, NULL);
|
|
} else {
|
|
window_schedule_redraw_grect(rootwin, &clip);
|
|
}
|
|
}
|
|
|
|
static void on_resized(ROOTWIN *rootwin)
|
|
{
|
|
GRECT g, work;
|
|
struct gui_window *gw;
|
|
|
|
gw = window_get_active_gui_window(rootwin);
|
|
|
|
//printf("resized...\n");
|
|
|
|
assert(gw != NULL);
|
|
|
|
if(gw == NULL)
|
|
return;
|
|
|
|
wind_get_grect(rootwin->aes_handle, WF_CURRXYWH, &g);
|
|
gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
|
|
|
|
if (rootwin->loc.g_w != g.g_w || rootwin->loc.g_h != g.g_h) {
|
|
|
|
/* resized */
|
|
toolbar_set_width(rootwin->toolbar, work.g_w);
|
|
|
|
if ( browser_window_has_content(gw->browser->bw) ) {
|
|
browser_window_reformat(gw->browser->bw, true, work.g_w, work.g_h);
|
|
}
|
|
}
|
|
if (rootwin->loc.g_x != g.g_x || rootwin->loc.g_y != g.g_y) {
|
|
/* moved */
|
|
toolbar_set_origin(rootwin->toolbar, work.g_x, work.g_y);
|
|
}
|
|
|
|
rootwin->loc = g;
|
|
}
|
|
|
|
static void on_file_dropped(ROOTWIN *rootwin, short msg[8])
|
|
{
|
|
char file[DD_NAMEMAX];
|
|
char name[DD_NAMEMAX];
|
|
char *buff=NULL;
|
|
int dd_hdl;
|
|
int dd_msg; /* pipe-handle */
|
|
long size;
|
|
char ext[32];
|
|
short mx,my,bmstat,mkstat;
|
|
struct gui_window *gw;
|
|
|
|
graf_mkstate(&mx, &my, &bmstat, &mkstat);
|
|
|
|
gw = window_get_active_gui_window(rootwin);
|
|
|
|
if( gw == NULL )
|
|
return;
|
|
|
|
if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED)
|
|
return;
|
|
|
|
dd_hdl = gemtk_dd_open( msg[7], DD_OK);
|
|
if( dd_hdl<0)
|
|
return; /* pipe not open */
|
|
memset( ext, 0, 32);
|
|
strcpy( ext, "ARGS");
|
|
dd_msg = gemtk_dd_sexts( dd_hdl, ext);
|
|
if( dd_msg<0)
|
|
goto error;
|
|
dd_msg = gemtk_dd_rtry( dd_hdl, (char*)&name[0], (char*)&file[0], (char*)&ext[0], &size);
|
|
if( size+1 >= PATH_MAX )
|
|
goto error;
|
|
if( !strncmp( ext, "ARGS", 4) && dd_msg > 0) {
|
|
gemtk_dd_reply(dd_hdl, DD_OK);
|
|
buff = (char*)malloc(sizeof(char)*(size+1));
|
|
if (buff != NULL) {
|
|
if (Fread(dd_hdl, size, buff ) == size) {
|
|
|
|
int sx, sy;
|
|
bool processed = false;
|
|
GRECT content_area;
|
|
|
|
buff[size] = 0;
|
|
|
|
LOG("file: %s, ext: %s, size: %d dropped at: %d,%d\n", (char *)buff, (char *)&ext, size, mx, my);
|
|
|
|
gui_window_get_scroll(gw, &sx, &sy);
|
|
|
|
window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
|
|
mx = mx - content_area.g_x;
|
|
my = my - content_area.g_y;
|
|
if((mx < 0 || mx > content_area.g_w)
|
|
|| (my < 0 || my > content_area.g_h))
|
|
return;
|
|
|
|
processed = browser_window_drop_file_at_point(gw->browser->bw,
|
|
mx+sx, my+sy,
|
|
NULL);
|
|
if(processed == true) {
|
|
nserror ret;
|
|
char *utf8_fn;
|
|
|
|
ret = utf8_from_local_encoding(buff, 0, &utf8_fn);
|
|
if (ret != NSERROR_OK) {
|
|
free(buff);
|
|
/* A bad encoding should never happen */
|
|
LOG("utf8_from_local_encoding failed");
|
|
assert(ret != NSERROR_BAD_ENCODING);
|
|
/* no memory */
|
|
goto error;
|
|
}
|
|
processed = browser_window_drop_file_at_point(gw->browser->bw,
|
|
mx+sx, my+sy,
|
|
utf8_fn);
|
|
free(utf8_fn);
|
|
}
|
|
|
|
if(processed == false) {
|
|
// TODO: use localized string:
|
|
if(gemtk_msg_box_show(GEMTK_MSG_BOX_CONFIRM, "Open File?") > 0) {
|
|
nsurl * ns_url = NULL;
|
|
char * tmp_url = local_file_to_url(buff);
|
|
if ((tmp_url != NULL)
|
|
&& nsurl_create(tmp_url, &ns_url) == NSERROR_OK) {
|
|
browser_window_navigate(gw->browser->bw, ns_url, NULL,
|
|
BW_NAVIGATE_HISTORY,
|
|
NULL, NULL, NULL);
|
|
nsurl_unref(ns_url);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
error:
|
|
if (buff) {
|
|
free(buff);
|
|
}
|
|
gemtk_dd_close( dd_hdl);
|
|
}
|
|
|
|
static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip)
|
|
{
|
|
struct rootwin_data_s * ud;
|
|
|
|
if (msg != WM_REDRAW) {
|
|
ud = gemtk_wm_get_user_data(win);
|
|
|
|
assert(ud);
|
|
|
|
toolbar_redraw(ud->rootwin->toolbar, clip);
|
|
}
|
|
}
|