/* * Copyright 2010 Ole Loots * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include "utils/log.h" #include "desktop/gui.h" #include "desktop/history_core.h" #include "desktop/netsurf.h" #include "desktop/browser.h" #include "desktop/mouse.h" #include "desktop/plotters.h" #include "atari/gui.h" #include "atari/browser_win.h" #include "atari/browser.h" #include "atari/misc.h" #include "atari/global_evnt.h" #include "atari/res/netsurf.rsh" #include "atari/browser.h" #include "atari/toolbar.h" #include "atari/statusbar.h" #include "atari/plot/plotter.h" bool cfg_rt_resize = false; bool cfg_rt_move = false; extern void * h_gem_rsrc; extern struct gui_window *input_window; extern GEM_PLOTTER plotter; void __CDECL std_szd( WINDOW * win, short buff[8], void * ); void __CDECL std_mvd( WINDOW * win, short buff[8], void * ); /* -------------------------------------------------------------------------- */ /* Module public functions: */ /* -------------------------------------------------------------------------- */ static void __CDECL evnt_window_arrowed( WINDOW *win, short buff[8], void *data ) { bool abs = false; LGRECT cwork; int value = BROWSER_SCROLL_SVAL; if( input_window == NULL ) { return; } browser_get_rect( input_window, BR_CONTENT, &cwork ); switch( buff[4] ) { case WA_UPPAGE: case WA_DNPAGE: value = cwork.g_h; break; case WA_LFPAGE: case WA_RTPAGE: value = cwork.g_w; break; default: break; } browser_scroll( input_window, buff[4], value, abs ); } int window_create( struct gui_window * gw, struct browser_window * bw, unsigned long inflags) { short buff[8]; OBJECT * tbtree; int err = 0; bool tb, sb; tb = (inflags & WIDGET_TOOLBAR ); sb = (inflags & WIDGET_STATUSBAR); short w,h, wx, wy, wh, ww; int flags = CLOSER | MOVER | NAME | FULLER | SMALLER ; gw->parent = NULL; 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->handle = WindCreate( flags,40, 40, app.w, app.h ); gw->root->cmproot = mt_CompCreate(&app, CLT_VERTICAL, 1, 1); WindSetPtr( gw->root->handle, WF_COMPONENT, gw->root->cmproot, NULL); if( tb ) { gw->root->toolbar = tb_create( gw ); assert( gw->root->toolbar ); mt_CompAttach( &app, gw->root->cmproot, gw->root->toolbar->comp ); } else { gw->root->toolbar = NULL; } gw->browser = browser_create( gw, bw, NULL, BT_ROOT, CLT_HORIZONTAL, 1, 1 ); mt_CompAttach( &app, gw->root->cmproot, gw->browser->comp ); if( sb ) { gw->root->statusbar = sb_create( gw ); mt_CompAttach( &app, gw->root->cmproot, gw->root->statusbar->comp ); } else { gw->root->statusbar = NULL; } WindSetStr(gw->root->handle, WF_ICONTITLE, (char*)"NetSurf"); EvntDataAttach( gw->root->handle, WM_CLOSED, evnt_window_close, NULL ); /* capture resize/move events so we can handle that manually */ if( !cfg_rt_resize ) { EvntAttach( gw->root->handle, WM_SIZED, evnt_window_resize); } else { EvntAdd( gw->root->handle, WM_SIZED, evnt_window_rt_resize, EV_BOT ); } if( !cfg_rt_move ) { EvntAttach( gw->root->handle, WM_MOVED, evnt_window_move ); } else { EvntAdd( gw->root->handle, WM_MOVED, evnt_window_rt_resize, EV_BOT ); } EvntAttach( gw->root->handle, WM_FORCE_MOVE, evnt_window_rt_resize ); EvntDataAdd( gw->root->handle, WM_DESTROY,evnt_window_destroy, NULL, EV_TOP ); EvntDataAdd( gw->root->handle, WM_ARROWED,evnt_window_arrowed, NULL, EV_TOP ); EvntDataAdd( gw->root->handle, WM_NEWTOP, evnt_window_newtop, &evnt_data, EV_BOT); EvntDataAdd( gw->root->handle, WM_TOPPED, evnt_window_newtop, &evnt_data, EV_BOT); EvntDataAttach( gw->root->handle, WM_ICONDRAW, evnt_window_icondraw, gw); /* OBJECT * tbut; RsrcGaddr( h_gem_rsrc, R_TREE, FAVICO , &tbut ); window_set_icon(gw, &tbut[]); */ /* TODO: check if window is openend as "foreground" window... */ window_set_focus( gw, BROWSER, gw->browser); return (err); } int window_destroy( struct gui_window * gw) { short buff[8]; int err = 0; if( gw->browser->type != BT_ROOT ) { return(0); } /* test this with frames: */ /* assert( gw->parent == NULL); */ if( input_window == gw ) input_window = NULL; if( gw->root ) { if( gw->root->toolbar ) tb_destroy( gw->root->toolbar ); if( gw->root->statusbar ) sb_destroy( gw->root->statusbar ); } LOG(("Freeing browser window")); if( gw->browser ) browser_destroy( gw->browser ); /* destroy the icon: */ /*window_set_icon(gw, NULL, false );*/ /* needed? */ /*listRemove( (LINKABLE*)gw->root->cmproot ); */ LOG(("Freeing root window")); if( gw->root ) { if( gw->root->cmproot ) mt_CompDelete( &app, gw->root->cmproot ); ApplWrite( _AESapid, WM_DESTROY, gw->root->handle->handle, 0, 0, 0, 0); EvntWindom( MU_MESAG ); gw->root->handle = NULL; free( gw->root ); gw->root = NULL; } return( err ); } void window_open( struct gui_window * gw) { LGRECT br; WindOpen(gw->root->handle, 20, 20, app.w/2, app.h/2 ); /* apply focus to the root frame: */ long lfbuff[8] = { CM_GETFOCUS }; mt_CompEvntExec( gl_appvar, gw->browser->comp, lfbuff ); /* recompute the nested component sizes and positions: */ browser_update_rects( gw ); browser_get_rect( gw, BR_CONTENT, &br ); plotter->move( plotter, br.g_x, br.g_y ); plotter->resize( plotter, br.g_w, br.g_h ); gw->browser->attached = true; if( gw->root->statusbar != NULL ){ gw->root->statusbar->attached = true; } snd_rdw( gw->root->handle ); } /* TODO void window_set_icon(struct gui_window * gw, void * data, bool is_rsc ) { #define CDT_ICON_TYPE_OBJECT 1UL #define CDT_ICON_TYPE_BITMAP 2UL void * prev_type; void * ico = DataSearch(&app, gw->root->handle, CDT_ICON ); if(ico != NULL) { prev_type = DataSearch(&app, gw->root->handle, CDT_ICON_TYPE ); if( prev_type == (void*)CDT_ICON_TYPE_OBJECT ){ mt_ObjcFree( &app, (OBJECT*)ico ); } if( prev_type == (void*)CDT_ICON_TYPE_BITMAP ){ bitmap_destroy(ico); } } if( data != NULL ) { DataAttach( &app, gw->root->handle, CDT_ICON, data); if(is_rsc) { DataAttach( &app, gw->root->handle, CDT_ICON_TYPE, CDT_ICON_TYPE_OBJECT); } else { DataAttach( &app, gw->root->handle, CDT_ICON_TYPE, CDT_ICON_TYPE_BITMAP); } } #undef CDT_ICON_TYPE_OBJECT #undef CDT_ICON_TYPE_BITMAP } */ /* update back forward buttons (see tb_update_buttons (bug) ) */ void window_update_back_forward( struct gui_window * gw) { tb_update_buttons( gw ); } static void window_redraw_controls(struct gui_window *gw, uint32_t flags) { LGRECT rect; /* redraw sliders manually, dunno why this is needed (mt_WindSlider should do the job anytime)!*/ browser_get_rect( gw, BR_VSLIDER, &rect); ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle, rect.g_x, rect.g_y, rect.g_w, rect.g_h ); browser_get_rect( gw, BR_HSLIDER, &rect); ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle, rect.g_x, rect.g_y, rect.g_w, rect.g_h ); /* send redraw to toolbar & statusbar & scrollbars: */ mt_CompGetLGrect(&app, gw->root->toolbar->comp, WF_WORKXYWH, &rect); ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle, rect.g_x, rect.g_y, rect.g_w, rect.g_h ); mt_CompGetLGrect(&app, gw->root->statusbar->comp, WF_WORKXYWH, &rect); ApplWrite( _AESapid, WM_REDRAW, gw->root->handle->handle, rect.g_x, rect.g_y, rect.g_w, rect.g_h ); } /* set focus to an arbitary element */ void window_set_focus( struct gui_window * gw, enum focus_element_type type, void * element ) { if( gw->root->focus.type != type || gw->root->focus.element != element ) { LOG(("Set focus: %p (%d)\n", element, type)); gw->root->focus.type = type; gw->root->focus.element = element; } } /* check if the url widget has focus */ bool window_url_widget_has_focus( struct gui_window * gw ) { assert( gw ); assert( gw->root ); if( gw->root->focus.type == URL_WIDGET && gw->root->focus.element != NULL ) { assert( ( &gw->root->toolbar->url == (struct s_url_widget*)gw->root->focus.element ) ); assert( GUIWIN_VISIBLE(gw) ); return true; } return false; } /* check if an arbitary window widget / or frame has the focus */ bool window_widget_has_focus( struct gui_window * gw, enum focus_element_type t, void * element ) { if( gw == NULL ) return( false ); if( element == NULL ){ assert( 1 != 0 ); return( (gw->root->focus.type == t ) ); } assert( gw->root != NULL ); return( ( element == gw->root->focus.element && t == gw->root->focus.type) ); } /* -------------------------------------------------------------------------- */ /* Non Public Modul event handlers: */ /* -------------------------------------------------------------------------- */ static void __CDECL evnt_window_destroy( WINDOW *win, short buff[8], void *data ) { LOG(("%s\n", __FUNCTION__ )); if( data ) free( data ); } static void __CDECL evnt_window_close( WINDOW *win, short buff[8], void *data ) { struct gui_window * gw = find_root_gui_window( win ); if( gw != NULL ) { browser_window_destroy( gw->browser->bw ); } } static void __CDECL evnt_window_newtop( WINDOW *win, short buff[8], void *data ) { input_window = find_root_gui_window( win ); LOG(("newtop: iw: %p, win: %p", input_window, win )); assert( input_window != NULL ); window_redraw_controls(input_window, 0); } static void __CDECL evnt_window_shaded( WINDOW *win, short buff[8], void *data ) { if(buff[0] == WM_SHADED){ LOG(("WM_SHADED, vis: %d, state: %d", GEMWIN_VISIBLE(win), win->status )); } if(buff[0] == WM_UNSHADED){ } } static void __CDECL evnt_window_icondraw( WINDOW *win, short buff[8], void * data ) { short x,y,w,h; struct gui_window * gw = (struct gui_window*)data; bool has_favicon = false; WindClear( win); WindGet( win, WF_WORKXYWH, &x, &y, &w, &h); if( has_favicon == false ) { OBJECT * tree; RsrcGaddr( h_gem_rsrc, R_TREE, ICONIFY , &tree ); tree->ob_x = x; tree->ob_y = y; tree->ob_width = w; tree->ob_height = h; mt_objc_draw( tree, 0, 8, buff[4], buff[5], buff[6], buff[7], app.aes_global ); } } static void __CDECL evnt_window_move( WINDOW *win, short buff[8] ) { short mx,my, mb, ks; short wx, wy, wh, ww, nx, ny; short r; short xoff, yoff; if( cfg_rt_move ) { std_mvd( win, buff, &app ); evnt_window_rt_resize( win, buff ); } else { wind_get( win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh ); if( graf_dragbox( ww, wh, wx, wy, app.x-ww, app.y, app.w+ww, app.h+wh, &nx, &ny )){ buff[4] = nx; buff[5] = ny; buff[6] = ww; buff[7] = wh; std_mvd( win, buff, &app ); evnt_window_rt_resize( win, buff ); } } } void __CDECL evnt_window_resize( WINDOW *win, short buff[8] ) { short mx,my, mb, ks; short wx, wy, wh, ww, nw, nh; short r; graf_mkstate( &mx, &my, &mb, &ks ); if( cfg_rt_resize ) { std_szd( win, buff, &app ); evnt_window_rt_resize( win, buff ); } else { wind_get( win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh ); r = graf_rubberbox(wx, wy, 20, 20, &nw, &nh); if( nw < 40 && nw < 40 ) return; buff[4] = wx; buff[5] = wy; buff[6] = nw; buff[7] = nh; std_szd( win, buff, &app ); evnt_window_rt_resize( win, buff ); } } /* perform the actual resize */ static void __CDECL evnt_window_rt_resize( WINDOW *win, short buff[8] ) { short x,y,w,h; struct gui_window * gw; LGRECT rect; bool resized; bool moved; if(buff[0] == WM_FORCE_MOVE ) { std_mvd(win, buff, &app); std_szd(win, buff, &app); } wind_get( win->handle, WF_WORKXYWH, &x, &y, &w, &h ); gw = find_root_gui_window( win ); assert( gw != NULL ); if(gw->root->loc.g_x != x || gw->root->loc.g_y != y ){ moved = true; gw->root->loc.g_x = x; gw->root->loc.g_y = y; browser_update_rects( gw ); } if(gw->root->loc.g_w != w || gw->root->loc.g_h != h ){ resized = true; /* report resize to component interface: */ browser_update_rects( gw ); browser_get_rect( gw, BR_CONTENT, &rect ); if( gw->browser->bw->current_content != NULL ) browser_window_reformat(gw->browser->bw, rect.g_w, rect.g_h ); gw->root->toolbar->url.scrollx = 0; window_redraw_controls(gw, 0); /* TODO: recalculate scroll position, istead of zeroing? */ } }