1 /*
2 * Copyright 2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * \file
21 * Amiga implementation of page info using core windows.
22 */
23
24 #include <stdint.h>
25 #include <stdlib.h>
26
27 #include <proto/intuition.h>
28
29 #include <classes/window.h>
30 #include <gadgets/layout.h>
31 #include <gadgets/scroller.h>
32 #include <gadgets/space.h>
33 #include <images/label.h>
34
35 #include <intuition/icclass.h>
36 #include <reaction/reaction_macros.h>
37
38 #include "utils/log.h"
39 #include "netsurf/keypress.h"
40 #include "netsurf/plotters.h"
41 #include "desktop/page-info.h"
42 #include "utils/messages.h"
43 #include "utils/nsoption.h"
44
45 #include "amiga/corewindow.h"
46 #include "amiga/libs.h"
47 #include "amiga/pageinfo.h"
48 #include "amiga/schedule.h"
49 #include "amiga/utf8.h"
50
51
52 /**
53 * Amiga page info window context
54 */
55 struct ami_pageinfo_window {
56 /** Amiga core window context */
57 struct ami_corewindow core;
58 /** core pageinfo */
59 struct page_info *pi;
60 };
61
62 /**
63 * destroy a previously created pageinfo window
64 */
65 static void
ami_pageinfo_destroy(struct ami_corewindow * ami_cw)66 ami_pageinfo_destroy(struct ami_corewindow *ami_cw)
67 {
68 nserror res;
69 struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
70 res = page_info_destroy(pageinfo_win->pi);
71 if (res == NSERROR_OK) {
72 ami_corewindow_fini(&pageinfo_win->core); /* closes the window for us */
73 }
74 }
75
76 /**
77 * close pageinfo window (callback)
78 */
79 static void
ami_pageinfo_close_cb(void * p)80 ami_pageinfo_close_cb(void *p)
81 {
82 ami_pageinfo_destroy((struct ami_corewindow *)p);
83 }
84
85 /**
86 * callback for unknown events on Amiga core window
87 * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP)
88 * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT)
89 *
90 * \param ami_cw The Amiga core window structure.
91 * \param result event as returned by RA_HandleInput()
92 * \return TRUE if window closed during event processing
93 */
94 static BOOL
ami_pageinfo_event(struct ami_corewindow * ami_cw,ULONG result)95 ami_pageinfo_event(struct ami_corewindow *ami_cw, ULONG result)
96 {
97 if((result & WMHI_CLASSMASK) == WMHI_INACTIVE) {
98 /* Window went inactive, so close it */
99 ami_pageinfo_destroy(ami_cw);
100 return TRUE;
101 }
102 return FALSE;
103 }
104
105 /**
106 * callback for mouse action for pageinfo on core window
107 *
108 * \param ami_cw The Amiga core window structure.
109 * \param mouse_state netsurf mouse state on event
110 * \param x location of event
111 * \param y location of event
112 * \return NSERROR_OK on success otherwise apropriate error code
113 */
114 static nserror
ami_pageinfo_mouse(struct ami_corewindow * ami_cw,browser_mouse_state mouse_state,int x,int y)115 ami_pageinfo_mouse(struct ami_corewindow *ami_cw,
116 browser_mouse_state mouse_state,
117 int x, int y)
118 {
119 bool did_something = false;
120 struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
121
122 if(page_info_mouse_action(pageinfo_win->pi, mouse_state, x, y, &did_something) == NSERROR_OK)
123 if (did_something == true) {
124 /* Something happened so we need to close ourselves */
125 ami_schedule(0, ami_pageinfo_close_cb, pageinfo_win);
126 }
127
128 return NSERROR_OK;
129 }
130
131 /**
132 * callback for keypress for pageinfo on core window
133 *
134 * \param ami_cw The Amiga core window structure.
135 * \param nskey The netsurf key code
136 * \return NSERROR_OK on success otherwise apropriate error code
137 */
138 static nserror
ami_pageinfo_key(struct ami_corewindow * ami_cw,uint32_t nskey)139 ami_pageinfo_key(struct ami_corewindow *ami_cw, uint32_t nskey)
140 {
141 struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
142
143 if (page_info_keypress(pageinfo_win->pi, nskey)) {
144 return NSERROR_OK;
145 }
146 return NSERROR_NOT_IMPLEMENTED;
147 }
148
149 /**
150 * callback on draw event for pageinfo on core window
151 *
152 * \param ami_cw The Amiga core window structure.
153 * \param x the x coordinate to draw
154 * \param y the y coordinate to draw
155 * \param r The rectangle of the window that needs updating.
156 * \param ctx The drawing context
157 * \return NSERROR_OK on success otherwise apropriate error code
158 */
159 static nserror
ami_pageinfo_draw(struct ami_corewindow * ami_cw,int x,int y,struct rect * r,struct redraw_context * ctx)160 ami_pageinfo_draw(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, struct redraw_context *ctx)
161 {
162 struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
163
164 page_info_redraw(pageinfo_win->pi, x, y, r, ctx);
165
166 return NSERROR_OK;
167 }
168
169 static nserror
ami_pageinfo_create_window(struct ami_pageinfo_window * pageinfo_win,ULONG left,ULONG top)170 ami_pageinfo_create_window(struct ami_pageinfo_window *pageinfo_win, ULONG left, ULONG top)
171 {
172 struct ami_corewindow *ami_cw = (struct ami_corewindow *)&pageinfo_win->core;
173 ULONG refresh_mode = WA_SmartRefresh;
174 struct Screen *scrn = ami_gui_get_screen();
175
176 if(nsoption_bool(window_simple_refresh) == true) {
177 refresh_mode = WA_SimpleRefresh;
178 }
179
180 ami_cw->objects[GID_CW_WIN] = WindowObj,
181 WA_ScreenTitle, ami_gui_get_screen_title(),
182 WA_Activate, TRUE,
183 WA_DepthGadget, FALSE,
184 WA_DragBar, FALSE,
185 WA_CloseGadget, FALSE,
186 WA_SizeGadget, FALSE,
187 WA_Borderless, TRUE,
188 WA_Left, left,
189 WA_Top, top,
190 WA_PubScreen, scrn,
191 WA_ReportMouse, TRUE,
192 refresh_mode, TRUE,
193 WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
194 IDCMP_RAWKEY | IDCMP_IDCMPUPDATE | IDCMP_INACTIVEWINDOW |
195 IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
196 WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
197 WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
198 IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
199 WINDOW_SharedPort, ami_gui_get_shared_msgport(),
200 WINDOW_UserData, pageinfo_win,
201 WINDOW_IconifyGadget, FALSE,
202 WINDOW_ParentGroup, ami_cw->objects[GID_CW_MAIN] = LayoutVObj,
203 LAYOUT_AddChild, ami_cw->objects[GID_CW_DRAW] = SpaceObj,
204 GA_ID, GID_CW_DRAW,
205 SPACE_Transparent, TRUE,
206 SPACE_BevelStyle, BVS_BOX,
207 GA_RelVerify, TRUE,
208 SpaceEnd,
209 EndGroup,
210 EndWindow;
211
212 if(ami_cw->objects[GID_CW_WIN] == NULL) {
213 return NSERROR_NOMEM;
214 }
215
216 return NSERROR_OK;
217 }
218
219 /* exported interface documented in amiga/pageinfo.h */
ami_pageinfo_open(struct browser_window * bw,ULONG left,ULONG top)220 nserror ami_pageinfo_open(struct browser_window *bw, ULONG left, ULONG top)
221 {
222 struct ami_pageinfo_window *ncwin;
223 nserror res;
224 int width, height;
225
226 ncwin = calloc(1, sizeof(struct ami_pageinfo_window));
227 if (ncwin == NULL) {
228 return NSERROR_NOMEM;
229 }
230
231 ncwin->core.wintitle = ami_utf8_easy((char *)messages_get("PageInfo"));
232
233 res = ami_pageinfo_create_window(ncwin, left, top);
234 if (res != NSERROR_OK) {
235 NSLOG(netsurf, INFO, "Page info init failed");
236 ami_utf8_free(ncwin->core.wintitle);
237 free(ncwin);
238 return res;
239 }
240
241 /* initialise Amiga core window */
242 ncwin->core.draw = ami_pageinfo_draw;
243 ncwin->core.key = ami_pageinfo_key;
244 ncwin->core.mouse = ami_pageinfo_mouse;
245 ncwin->core.close = ami_pageinfo_destroy;
246 ncwin->core.event = ami_pageinfo_event;
247
248 res = ami_corewindow_init(&ncwin->core);
249 if (res != NSERROR_OK) {
250 ami_utf8_free(ncwin->core.wintitle);
251 DisposeObject(ncwin->core.objects[GID_CW_WIN]);
252 free(ncwin);
253 return res;
254 }
255
256 res = page_info_create(ncwin->core.cb_table,
257 (struct core_window *)ncwin,
258 bw,
259 &ncwin->pi);
260
261 if (res != NSERROR_OK) {
262 ami_utf8_free(ncwin->core.wintitle);
263 DisposeObject(ncwin->core.objects[GID_CW_WIN]);
264 free(ncwin);
265 return res;
266 }
267
268 if(page_info_get_size(ncwin->pi, &width, &height) == NSERROR_OK) {
269 /* Set window to the correct size.
270 * TODO: this should really set the size of ncwin->core.objects[GID_CW_DRAW]
271 * and let the window adjust, here we've hardcoded to add 6x4px as that's
272 * what window.class does before v45.
273 */
274 SetAttrs(ncwin->core.objects[GID_CW_WIN], WA_InnerWidth, width + 6, WA_InnerHeight, height + 4, TAG_DONE);
275 }
276
277 return NSERROR_OK;
278 }
279
280