Drop the bool operator for ObjectURI, to avoid getting the kind of side-effect that...
[gnash.git] / gui / haiku / haiku.cpp
blob81495f735b127fc671e440069c5fe65baa1edfc7
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program 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, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "gnashconfig.h"
22 #endif
24 #include "RunResources.h"
26 #include <boost/format.hpp>
28 #include "gnash.h"
29 #include "adipe.h"
30 #include "haikusup.h"
33 #include <interface/Font.h>
34 #include <Application.h>
35 #include <Alert.h>
36 #include <Window.h>
37 #include <Screen.h>
39 using namespace std;
41 #ifndef RENDERER_AGG
42 #error Haiku gui requires AGG renderer
43 #endif
45 namespace gnash
48 const int32 GNASH_PULSE = 'GPLS';
49 const int32 GNASH_SEND_PULSE = 'GSPL';
50 const int32 GNASH_QUITTING = 'GQUI';
53 class BeWin : public BWindow
55 HaikuGui *_gui;
56 BRect _unfullscreen_frame;
57 bool _fullscreen;
58 public:
59 BeWin(BRect frame, const char *title, HaikuGui *gui)
60 : BWindow(frame, title, B_TITLED_WINDOW, 0), _gui(gui),
61 _fullscreen(false)
65 bool QuitRequested()
67 be_app_messenger.SendMessage(B_QUIT_REQUESTED);
68 BWindow::QuitRequested();
69 return false;
72 void FrameResized(float width, float height)
74 BMessage msg(GNASH_RESIZE);
75 if (msg.AddFloat("w", width) != B_OK
76 || msg.AddFloat("h", height) != B_OK)
77 QQ(1);
78 else
79 be_app_messenger.SendMessage(&msg);
82 void setFullscreenEtc()
84 QQ(8);
85 if (_fullscreen == true)
86 return;
87 _fullscreen = true;
89 BScreen s(this);
90 BRect r(s.Frame());
91 _unfullscreen_frame = Frame();
92 MoveTo(0,0);
93 ResizeTo(r.Width(), r.Height());
96 void ScreenChanged(BRect frame, color_space mode)
98 (void) mode;
100 QQ(8);
101 if (_fullscreen == false)
102 return;
103 // XXX perform in beapp thread
104 MoveTo(0,0);
105 ResizeTo(frame.Width(), frame.Height());
108 void unsetFullscreenEtc()
110 QQ(8);
111 if (_fullscreen == false)
112 return;
113 _fullscreen = false;
114 MoveTo(_unfullscreen_frame.left, _unfullscreen_frame.top);
115 ResizeTo(_unfullscreen_frame.Width(), _unfullscreen_frame.Height());
121 class BeApp : public BApplication
123 HaikuGui *_gui;
124 BWindow *_win;
125 thread_id _pulse_tid;
126 time_t _start_t;
127 time_t _timeout;
128 int32 _mouse_moves_this_pulse;
129 int32 _mousemovedx, _mousemovedy;
130 public:
131 BeApp(HaikuGui *gui)
132 : BApplication("application/gnash-player"),
133 _gui(gui), _win(NULL),
134 _pulse_tid(-1),
135 _start_t(time(NULL)),
136 _timeout(0),
137 _mouse_moves_this_pulse(0),
138 _mousemovedx(0), _mousemovedy(0)
140 _pulse_tid = spawn_thread(SendPulses, "Pulses", B_NORMAL_PRIORITY, this);
141 if (_pulse_tid <= 0) {
142 throw runtime_error(_("spawn_thread failed"));
144 if (B_OK != resume_thread(_pulse_tid)) {
145 throw runtime_error(_("resume_thread failed"));
150 static int32
151 SendPulses(void *data)
153 BeApp *that =
154 static_cast<BeApp*>(data);
155 assert(that != NULL);
156 int32 i = that->SendPulsesEtc();
157 if (i != 0) {
158 boost::format fmt(_("pulses thread returned %d"));
159 fmt = fmt % i;
160 log_error(fmt.str());
162 return i;
166 int32
167 SendPulsesEtc()
169 BMessage m(GNASH_PULSE);
170 int32 code;
171 thread_id sender;
173 while (true)
175 if (B_OK != be_app_messenger.SendMessage(&m))
176 return -1;
178 unsigned int interval =
179 _gui->getInterval();
180 if (interval == 0)
181 interval = 15;
182 // interval in miliseconds, 1000 * interval in microseconds
183 usleep(1000 * interval);
185 do {
186 code = receive_data(&sender, NULL, 0);
187 } while (code == B_INTERRUPTED);
188 switch (code)
190 case GNASH_SEND_PULSE:
191 break;
192 case GNASH_QUITTING:
193 return 0;
194 default:
195 return -1;
198 return 0;
201 void setTimeout(time_t timeout)
203 _timeout = timeout;
206 virtual ~BeApp()
208 status_t st, exit_value;
209 do {
210 st = send_data(_pulse_tid, GNASH_QUITTING, NULL, 0);
211 } while (st == B_INTERRUPTED);
212 if (st == B_OK)
213 wait_for_thread(_pulse_tid, &exit_value);
216 bool QuitRequested()
218 BApplication::QuitRequested();
219 return true;
222 bool Timedout()
224 return _timeout && time(NULL) - _start_t > _timeout;
227 void setFullscreenEtc()
229 assert(_win != NULL);
230 static_cast<BeWin*>(_win)->setFullscreenEtc();
233 void unsetFullscreenEtc()
235 assert(_win != NULL);
236 static_cast<BeWin*>(_win)->unsetFullscreenEtc();
239 void MessageReceived(BMessage *msg)
241 switch (msg->what)
243 case GNASH_PULSE:
244 if (_mouse_moves_this_pulse > 3)
245 _gui->notifyMouseMove(_mousemovedx, _mousemovedy);
246 _mouse_moves_this_pulse = 0;
247 _gui->GnashPulse();
248 if (B_OK != send_data(_pulse_tid, GNASH_SEND_PULSE, NULL, 0)) {
249 log_error(_("send_data failed"));
250 Quit();
252 break;
253 case GNASH_RESIZE:
255 float width, height;
256 if (msg->FindFloat("w", &width) != B_OK
257 || msg->FindFloat("h", &height) != B_OK)
258 QQ(1);
259 else
260 _gui->resize_view(width+1, height+1);
261 break;
263 case GNASH_HIDDEN:
265 _gui->Hidden();
266 break;
268 case GNASH_SHOWN:
270 _gui->Shown();
271 break;
273 case GNASH_SET_FULLSCREEN:
274 _gui->setFullscreenEtc();
275 break;
276 case GNASH_UNSET_FULLSCREEN:
277 _gui->unsetFullscreenEtc();
278 break;
279 case GNASH_MOUSE_CLICKED:
281 bool pressed;
282 int32 mask;
283 if (B_OK != msg->FindBool("pressed", &pressed)
284 || B_OK != msg->FindInt32("mask", &mask))
285 QQ(1);
286 else
287 _gui->notifyMouseClick(pressed);
288 break;
290 case GNASH_MOUSE_MOVED:
292 ++ _mouse_moves_this_pulse;
293 int32 x, y;
294 if (B_OK != msg->FindInt32("x", &x)
295 || B_OK != msg->FindInt32("y", &y))
296 QQ(1);
297 else
299 if (_mouse_moves_this_pulse > 3)
301 _mousemovedx = x;
302 _mousemovedy = y;
303 } else
304 _gui->notifyMouseMove(x, y);
306 break;
308 case GNASH_KEY_EVENT:
310 int32 key, modifiers;
311 bool pressed;
312 if (B_OK != msg->FindInt32("key", &key)
313 || B_OK != msg->FindInt32("modifiers", &modifiers)
314 || B_OK != msg->FindBool("pressed", &pressed))
315 QQ(1);
316 else
317 _gui->notify_key_event(static_cast<gnash::key::code>(key), modifiers, pressed);
318 break;
320 default:
321 BApplication::MessageReceived(msg);
325 void
326 ReadyToRun()
330 bool
331 CreateWindow(int width, int height, int xPosition, int yPosition,
332 const char *title)
334 assert(_win == NULL);
335 QQ(8);
336 _win = new BeWin(BRect(xPosition, yPosition, xPosition+width-1, yPosition+height-1),
337 title, _gui);
338 _win->Show();
339 return true;
342 BWindow**
343 GetWinAddr()
345 return &_win;
350 HaikuGui::HaikuGui(unsigned long xid, float scale, bool loop, RunResources& r)
351 : Gui(xid, scale, loop, r), _app(NULL),
352 _glue(this, xid), _timeout(0)
354 QQ(8);
357 HaikuGui::~HaikuGui()
359 GNASH_REPORT_FUNCTION;
361 delete _app;
364 bool
365 HaikuGui::init(int argc, char **argv[])
367 QQ(8);
368 GNASH_REPORT_FUNCTION;
369 _app = new BeApp(this);
371 // if (_xid)
372 // log_error (_("Ignoring request to display in X11 window"));
374 char c;
375 int origopterr = opterr;
377 optind = 0;
378 opterr = 0;
380 while ((c = getopt(argc, *argv, "D:")) != -1) {
381 if (c == 'D') {
382 // Terminate if no filename is given.
383 if (!optarg) {
384 std::cout <<
385 _("# FATAL: No filename given with -D argument.") << std::endl;
386 return false;
388 _sharefilename = optarg;
393 opterr = origopterr;
395 _glue.init(argc, argv, _app->GetWinAddr(), _sharefilename);
397 _renderer.reset(_glue.createRenderHandler(32));
398 if ( ! _renderer ) return false;
400 return true;
403 bool
404 HaikuGui::createWindow(const char *title, int width, int height,
405 int xPosition, int yPosition)
407 GNASH_REPORT_FUNCTION;
408 if (xPosition == -1 && yPosition == -1)
410 xPosition = 200;
411 yPosition = 200;
413 _width = width;
414 _height = height;
418 if (_xid == 0)
420 bool b = _app->CreateWindow(width, height, xPosition, yPosition,
421 title);
422 if (b == false)
423 return false;
424 } else {
426 _glue.prepDrawingArea(_width, _height, 0/*sdl_flags*/);
427 _glue.ViewNeeded();
428 _runResources.setRenderer(_renderer);
430 return true;
433 bool
434 HaikuGui::run()
436 GNASH_REPORT_FUNCTION;
437 _app->Run();
438 return ! _app->Timedout();
441 void
442 HaikuGui::renderBuffer()
444 _glue.render();
447 void
448 HaikuGui::setInterval(unsigned int interval)
450 _interval = interval;
453 void
454 HaikuGui::setTimeout(unsigned int timeout)
456 _timeout = timeout;
457 _app->setTimeout((timeout+999)/1000);
460 void
461 HaikuGui::error(const std::string &msg)
463 BAlert *alert =
464 new BAlert("Error", msg.c_str(), "Dismiss", NULL, NULL,
465 B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT);
466 alert->Go();
469 bool
470 HaikuGui::yesno(const std::string& question)
472 BAlert *alert =
473 new BAlert("yes/no", question.c_str(), "Yes", "No", NULL,
474 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
475 int32 answer = alert->Go();
476 return answer == 0;
479 void
480 HaikuGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
482 _glue.setInvalidatedRegions(ranges);
485 bool
486 HaikuGui::createMenu()
488 GNASH_REPORT_FUNCTION;
489 return false;
492 bool
493 HaikuGui::createMenuBar()
495 GNASH_REPORT_FUNCTION;
496 return false;
499 bool
500 HaikuGui::setupEvents()
502 GNASH_REPORT_FUNCTION;
503 return false;
506 void
507 HaikuGui::setFullscreen()
509 BMessage m(GNASH_SET_FULLSCREEN);
510 be_app_messenger.SendMessage(&m);
513 void
514 HaikuGui::setFullscreenEtc()
516 //_glue.BlankScreen();
517 if (_xid != 0)
519 bool b = _app->CreateWindow(_width, _height, 0, 0,
520 "Gnash");
521 if (b == false)
523 return;
525 //_glue.prepDrawingArea(_width+5, _height, 0/*sdl_flags*/);
526 //_glue.prepDrawingArea(_width, _height, 0/*sdl_flags*/);
527 _glue.ViewNeeded();
529 _app->setFullscreenEtc();
532 void
533 HaikuGui::unsetFullscreen()
535 BMessage m(GNASH_UNSET_FULLSCREEN);
536 be_app_messenger.SendMessage(&m);
539 void
540 HaikuGui::unsetFullscreenEtc()
542 //_glue.BlankScreen();
543 _app->unsetFullscreenEtc();
544 if (_xid != 0)
546 (*_app->GetWinAddr())->LockLooper();
547 (*_app->GetWinAddr())->Quit();
548 (*_app->GetWinAddr()) = NULL;
549 _glue.ViewNoMore();
551 //std::cerr << _width << " " << _height << std::endl;
552 //_glue.prepDrawingArea(_width, _height, 0/*sdl_flags*/);
555 void HaikuGui::GnashPulse()
557 if (_app->Timedout())
559 _app->Quit();
560 return ;
563 Gui::advance_movie(this);
566 unsigned int
567 HaikuGui::getInterval()
569 return _interval;
572 void
573 HaikuGui::resize_view(int width, int height)
575 std::cerr << width << " " << height << std::endl;
576 _glue.prepDrawingArea(width, height, 0);
577 Gui::resize_view(width, height);
580 void
581 HaikuGui::Shown()
583 _glue.Shown();
586 void
587 HaikuGui::Hidden()
589 _glue.Hidden();