Update with current status
[gnash.git] / gui / gui.h
blob1bef998f7f8742c30fd6e95cff7f9e34d4645a14
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
3 // 2011 Free Software 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
19 #ifndef GNASH_GUI_H
20 #define GNASH_GUI_H
22 #ifdef HAVE_CONFIG_H
23 #include "gnashconfig.h"
24 #endif
26 #include <boost/intrusive_ptr.hpp>
27 #include <memory>
28 #include <string>
29 #include <map>
30 #include <utility>
31 #include <functional>
33 #include "snappingrange.h" // for InvalidatedRanges
34 #include "GnashKey.h"
35 #include "VirtualClock.h"
36 #include "SystemClock.h"
37 #include "GnashEnums.h"
38 #include "movie_root.h"
40 #ifdef USE_SWFTREE
41 #include "tree.hh" // for tree
42 #endif
44 // Define this to enable fps debugging without touching
45 // gnashconfig.h
46 //#define GNASH_FPS_DEBUG
48 /// Define this to disable region updates debugging altogether. If undefined,
49 /// debugging will be a runtime option. The flag and flag-setting functions
50 /// will not be disabled (too ugly).
51 ///
52 /// This should go in gnashconfig.h
53 ///
54 /// This has the side effect that all frames will be re-rendered completely
55 /// but in contrast to FORCE_REDRAW it won't re-render when no motion
56 /// has been detected in the movie (for example when the movie is stopped).
57 ///
58 //#define DISABLE_REGION_UPDATES_DEBUGGING 1
61 /// Define this to support keyboard-based pointer movements
62 #define ENABLE_KEYBOARD_MOUSE_MOVEMENTS 1
64 // Forward declarations
65 namespace gnash {
66 class SWFRect;
67 class ScreenShotter;
68 class RunResources;
69 class movie_root;
70 class movie_definition;
71 class Renderer;
72 class SWFRect;
74 namespace boost {
75 template <typename Signature> class function;
78 namespace gnash {
80 /// Enumerates mouse cursor types.
81 enum gnash_cursor_type {
82 CURSOR_HAND,
83 CURSOR_NORMAL,
84 CURSOR_INPUT
87 /// Parent class from which all GUI implementations will depend.
88 class Gui {
90 public:
92 virtual ~Gui();
94 /// \brief/
95 /// Initialise the gui and the associated renderer.
96 ///
97 /// @param argc The commandline argument count.
98 /// @param argv The commandline arguments.
99 /// @return True on success; false on failure.
100 virtual bool init(int argc, char **argv[]) = 0;
102 /// Set main loop delay in milliseconds.
103 virtual void setInterval(unsigned int interval) {
104 _interval = interval;
107 /// Return the clock provided by this Gui.
109 /// The Gui clock will be paused when the gui is put
110 /// in pause mode and resumed when gui playback is resumed.
112 virtual VirtualClock& getClock() { return _virtualClock; }
114 /// Set the time in milliseconds after which the programme should exit.
115 virtual void setTimeout(unsigned int timeout) = 0;
117 void setScreenShotter(std::unique_ptr<ScreenShotter> ss);
119 /// \brief
120 /// Create and display our window.
122 /// @param title The window title.
123 /// @param width The desired window width in pixels.
124 /// @param height The desired window height in pixels.
125 /// @param xPosition The desired window X position from the top left corner.
126 /// @param yPosition The desired window Y position from the top left corner.
127 virtual bool createWindow(const char* title, int width, int height,
128 int xPosition = 0, int yPosition = 0) = 0;
130 virtual void resizeWindow(int width, int height);
132 /// Start main rendering loop.
133 virtual bool run() = 0;
135 /// Always called on exit.
137 /// Handles any common functions, then calls virtual quitUI().
138 void quit();
140 /// Render the current buffer.
141 /// For OpenGL, this means that the front and back buffers are swapped.
142 virtual void renderBuffer() = 0;
144 /// Gives the GUI a *hint* which region of the stage should be redrawn.
146 /// There is *no* restriction what the GUI might do with these coordinates.
147 /// Normally the GUI forwards the information to the renderer so that
148 /// it avoids rendering regions that did not change anyway. The GUI can
149 /// also alter the bounds before passing them to the renderer and it's
150 /// absolutely legal for the GUI to simply ignore the call.
152 /// Coordinates are in TWIPS!
154 /// Note this information is given to the GUI and not directly to the
155 /// renderer because both of them need to support this feature for
156 /// correct results. It is up to the GUI to forward this information to
157 /// the renderer.
159 // does not need to be implemented (optional feature),
160 // but still needs to be available.
162 virtual void setInvalidatedRegion(const SWFRect& bounds);
163 virtual void setInvalidatedRegions(const InvalidatedRanges& ranges);
165 // Called right before rendering anything (after setInvalidatedRegion).
166 // Used by GTK-AGG.
167 virtual void beforeRendering() { /* nop */ };
169 // Should return TRUE when the GUI/Renderer combination supports multiple
170 // invalidated bounds regions.
171 virtual bool want_multiple_regions() { return false; }
173 /// Asks the GUI handler if the next frame should be redrawn completely.
175 /// For example, when the contents of the player window have been destroyed,
176 /// then want_redraw() should return true so that setInvalidatedRegion() is
177 /// called with the coordinates of the complete screen.
178 virtual bool want_redraw();
180 /// Sets the current mouse cursor for the Gui window.
181 virtual void setCursor(gnash_cursor_type newcursor);
183 virtual void setClipboard(const std::string& copy);
185 // Information for System.capabilities to be reimplemented in
186 // each gui.
187 virtual double getPixelAspectRatio() const { return 0; }
189 virtual std::pair<int, int> screenResolution() const {
190 return std::make_pair(0, 0);
193 virtual double getScreenDPI() const { return 0; }
195 /// Get the screen color type.
197 /// The choice is between "color" and something designating
198 /// monochrome (not sure what). If this isn't implemented in the
199 /// gui we return "color".
200 virtual std::string getScreenColor() const {
201 return "color";
204 /// @return Whether or not the movie should be looped indefinitely.
205 bool loops() const { return _loop; }
207 /// @return Whether the movie is running fullscreen or not.
208 bool isFullscreen() const { return _fullscreen; }
210 /// Mouse notification callback to be called when the mouse is moved.
212 /// @param x The mouse coordinate X component in user/window
213 /// coordinate space (pixels).
214 /// @param y The mouse coordinate Y component in user/window
215 /// coordinate space (pixels).
216 void notifyMouseMove(int x, int y);
218 /// Mouse notification callback to be called when the mouse is clicked.
220 /// @param mouse_pressed Determines whether the mouse button is being
221 /// pressed (true) or being released (false)
222 void notifyMouseClick(bool mouse_pressed);
224 /// Send a mouse wheel event to the stage.
226 /// @param delta A number expressing the extent of the wheel scroll.
227 void notifyMouseWheel(int delta);
229 /// Key event notification to be called when a key is pressed or depressed
231 /// @param k The key code.
232 /// @param modifier
233 /// Modifier key identifiers from gnash::key::modifier ORed together
234 /// @param pressed
235 /// Determines whether the key is being pressed (true)
236 /// or being released (false)
238 void notify_key_event(gnash::key::code k, int modifier, bool pressed);
240 /// Resize the client area view and the window accordingly.
242 /// @param width The desired width in pixels.
243 /// @param height The desired height in pixels.
244 void resize_view(int width, int height);
246 /// Update stage SWFMatrix accordingly to window size and flash Stage
247 /// configuration (scaleMode, alignment)
249 /// This method should be called from the core lib when Stage configuration
250 /// change or is called by resize_view.
252 void updateStageMatrix();
254 /// \brief
255 /// Give movie an heart-beat.
257 /// This is to take place after the
258 /// interval specified in the call to setInterval().
260 /// Wheter or not this beat advanced the movie to the next frame
261 /// depends on elapsed time since last advancement.
263 /// @return true if this beat resulted in actual frame advancement.
265 bool advanceMovie(bool doDisplay = true);
267 /// Convenience static wrapper around advanceMovie for callbacks happiness.
269 /// NOTE: this function always return TRUE, for historical reasons.
270 /// TODO: bring code up-to-date to drop this legacy return code..
271 ///
272 static bool advance_movie(Gui* gui) {
273 gui->advanceMovie();
274 return true;
277 /// Force immediate redraw
279 void refreshView();
281 /// Attempt to run in a fullscreen window both for plugin and
282 /// standalone player.
284 /// Use isFullscreen() to see if gnash thinks
285 /// it's running in fullscreen or not. The switch to fullscreen may
286 /// fail if, for instance, the window manager refuses to allow it, but
287 /// the flag will be set anyway.
288 virtual void setFullscreen();
290 /// Return from fullscreen to normal mode.
292 virtual void unsetFullscreen();
294 /// Hide the menu bar when using standalone player
296 virtual void hideMenu();
298 /// Sets whether the gui should show the system mouse pointer
300 /// @param show true if the mouse should be shown.
301 /// @return true if the state changed.
302 virtual bool showMouse(bool show);
304 /// Sets whether the menus should be shown (for fscommand)
306 /// @param show true if the menu bar should be shown.
307 virtual void showMenu(bool show);
309 /// Sets whether scaling should be allowed (for fscommand)
311 /// @param allow true if stage scaling should be allowed
312 virtual void allowScale(bool allow);
314 // Toggle between fullscreen and normal mode
315 void toggleFullscreen();
317 /// Put the application in "stop" mode
319 /// When in stop mode the application won't be advanced.
321 void stop();
323 /// Put the application in "play" mode
325 /// When in play mode the application will be advanced as usual.
327 void play();
329 /// Toggle between "stop" and "play" mode
331 /// See stop() and play()
333 void pause();
335 /// Start the movie
337 /// This function will create an instance of the registered top-level
338 /// movie definition, set variables into it and place it to the stage.
340 void start();
342 /// See stop(), play() and pause()
343 bool isStopped() const { return _stopped; }
345 /// Whether gnash is is running as a plugin
346 bool isPlugin() const { return ((_xid)); }
348 /// Take a screenshot now!
349 void takeScreenShot();
351 /// Set the maximum number of frame advances before Gnash exits.
352 void setMaxAdvances(unsigned long ul) { if (ul) _maxAdvances = ul; }
354 void showUpdatedRegions(bool x) { _showUpdatedRegions = x; }
355 bool showUpdatedRegions() const { return _showUpdatedRegions; }
357 /// Instruct the core to restart the movie and
358 /// set state to play(). This does not change pause
359 /// state.
360 void restart();
362 /// Set rendering quality, if not locked by RC file..
363 void setQuality(Quality q);
365 /// Get current rendering quality
366 Quality getQuality() const;
368 /// Toggle sound state between muted and unmuted. If
369 /// there is no active sound handler this does nothing.
370 void toggleSound();
372 #ifdef GNASH_FPS_DEBUG
373 /// Set the interval between FPS debugging prints
375 /// See fpsCounterTick()
377 void setFpsTimerInterval(float interval)
379 assert(interval >= 0.0);
380 fps_timer_interval = interval;
382 #endif // def GNASH_FPS_DEBUG
385 #ifdef USE_SWFTREE
386 /// Return a tree containing information about the movie playing.
387 std::unique_ptr<movie_root::InfoTree> getMovieInfo() const;
388 #endif
390 typedef std::map<std::string, std::string> VariableMap;
392 /// Add variables to set into instances of the top-level movie definition
393 void addFlashVars(VariableMap& vars);
395 /// Set the definition of top-level movie
396 void setMovieDefinition(movie_definition* md);
398 /// Set the stage to advance/display
399 void setStage(movie_root* stage);
401 /// Set the name of a file to dump audio to
402 void setAudioDump(const std::string& fname) {
403 _audioDump = fname;
406 /// The root movie, or "Stage"
407 movie_root* getStage() { return _stage; };
409 /// Handle error message from the core
411 /// @param msg The error message recieved
413 virtual void error(const std::string& /*msg*/) {}
415 /// Prompt user with a question she can answer with yes/no
417 /// @param question
418 /// The question to ask user
420 /// @return
421 /// true for YES, false for NO
423 /// The default implementation always returns true.
425 virtual bool yesno(const std::string& question);
427 /// Width of a window pixel, in stage pseudopixel units.
428 float getXScale() const { return _xscale; };
430 /// Height of a window pixel, in stage pseudopixel units.
431 float getYScale() const { return _yscale; };
433 /// Height of a window pixel, in stage pseudopixel units.
434 float getFPS() const { return (_movieDef) ? _movieDef->get_frame_rate() : 0;
437 protected:
439 /// Default constructor. Initialises members to safe defaults.
440 Gui(RunResources& r);
442 /** \brief
443 * Expanded constructor for more control over member values.
445 * @param xid The X11 Window ID to attach to. If this is argument is zero,
446 * a new window is created.
448 * @param scale The scale used to resize the window size, which has been
449 * established by extracting information from the SWF file.
451 * @param loop Defines whether or not the movie should be played once or
452 * looped indefinitely.
454 * @param depth Colour depth to be used in the client area of our window.
456 Gui(unsigned long xid, float scale, bool loop, RunResources& r);
458 /// End main rendering loop calling GUI-specific exit functions.
460 /// Do not call this directly. Call quit() instead.
462 /// The default implementation calls exit(EXIT_SUCCESS), which isn't nice.
463 /// Please implement the proper main loop quitter in the subclasses.
464 virtual void quitUI() {
465 std::exit(EXIT_SUCCESS);
468 /// Watch a file descriptor.
470 /// An implementing Gui should monitor the file descriptor in its main
471 /// loop. When the file descriptor is triggered, the implementation should
472 /// call callCallback().
474 /// @param fd The file descriptor to be watched
475 virtual bool watchFD(int /* fd */)
477 log_unimpl("This GUI does not implement FD watching.");
478 return false;
482 /// Determines if playback should restart after the movie ends.
483 bool _loop;
485 /// The X Window ID to attach to. If zero, we create a new window.
486 unsigned long _xid;
488 // This would be 0,0,_width,_height, so maybe
489 // we should not duplicate the info with those
490 // explicit values too..
491 geometry::Range2d<int> _validbounds;
493 /// Desired window width.
494 int _width;
496 /// Desired window height.
497 int _height;
499 /// Per-run resources
500 RunResources& _runResources;
502 /// Main loop interval: the time between successive advance_movie calls.
503 unsigned int _interval;
505 /// The handler which is called to update the client area of our window.
506 std::shared_ptr<Renderer> _renderer;
508 /// Signals that the next frame must be re-rendered completely because the
509 /// window size did change.
510 bool _redraw_flag;
512 // True if Gnash is running in fullscreen
513 bool _fullscreen;
515 // True if mouse pointer is showing
516 bool _mouseShown;
518 // Maximum number of advances before exit; 0 for no limit.
519 unsigned long _maxAdvances;
521 /// Counter to keep track of frame advances
522 unsigned long _advances;
524 /// Name of a file to dump audio to
525 std::string _audioDump;
527 /// Called by Gui::stop(). This can be used by GUIs to implement pause
528 /// widgets (so that resuming a stopped animation is more user-friendly)
529 virtual void stopHook() {}
531 /// Called by Gui::play().
532 virtual void playHook() {}
534 /// Determines whether the Gui is visible (not obscured).
535 virtual bool visible() { return true; }
536 private:
538 struct Display;
540 std::map<int /* fd */, std::function<void ()> > _fd_callbacks;
542 /// Width of a window pixel, in stage pseudopixel units.
543 float _xscale;
545 /// Height of a window pixel, in stage pseudopixel units.
546 float _yscale;
548 /// Window pixel X offset of stage origin
549 std::int32_t _xoffset;
551 /// Window pixel Y offset of stage origin
552 std::int32_t _yoffset;
554 bool display(movie_root* m);
556 #ifdef GNASH_FPS_DEBUG
557 unsigned int fps_counter;
559 float fps_rate_min, fps_rate_max;
561 // Number of calls to fpsCounterTick, which is also
562 // the number of calls to movie_advance()
563 unsigned int fps_counter_total;
565 std::uint64_t fps_timer, fps_start_timer;
567 /// The time, in seconds, between prints (which also resets the fps counter).
569 /// interval must be >= 0
571 float fps_timer_interval;
573 /// Number of frames rendering of which was dropped
574 unsigned int frames_dropped;
576 /// \brief
577 /// Should be called on every frame advance (including inter-frames caused
578 /// by mouse events).
580 /// Based on fps-timer_interval. See setFpsTimerInterval.
582 void fpsCounterTick();
584 #endif // def GNASH_FPS_DEBUG
586 VariableMap _flashVars;
588 boost::intrusive_ptr<movie_definition> _movieDef;
590 /// The root movie, or "Stage"
591 movie_root* _stage;
593 /// True if the application has been put into "stop" mode
594 bool _stopped;
596 /// True if the application didn't start yet
597 bool _started;
599 /// If true, updated regions (invalidated ranges) are visibly outlined.
600 bool _showUpdatedRegions;
602 SystemClock _systemClock;
603 InterruptableVirtualClock _virtualClock;
605 /// Checked on each advance for screenshot activity if it exists.
606 std::unique_ptr<ScreenShotter> _screenShotter;
608 #ifdef ENABLE_KEYBOARD_MOUSE_MOVEMENTS
609 int _xpointer;
610 int _ypointer;
611 bool _keyboardMouseMovements;
612 int _keyboardMouseMovementsStep;
613 #endif // ENABLE_KEYBOARD_MOUSE_MOVEMENTS
616 /// Named constructors
617 namespace gui {
618 std::unique_ptr<Gui> createFBGui(unsigned long xid, float scale, bool loop, RunResources& r);
620 std::unique_ptr<Gui> createGTKGui(unsigned long xid, float scale, bool loop, RunResources& r);
621 std::unique_ptr<Gui> createKDEGui(unsigned long xid, float scale, bool loop, RunResources& r);
622 std::unique_ptr<Gui> createQt4Gui(unsigned long xid, float scale, bool loop, RunResources& r);
623 std::unique_ptr<Gui> createSDLGui(unsigned long xid, float scale, bool loop, RunResources& r);
624 std::unique_ptr<Gui> createFLTKGui(unsigned long xid, float scale, bool loop, RunResources& r);
625 std::unique_ptr<Gui> createAQUAGui(unsigned long xid, float scale, bool loop, RunResources& r);
626 std::unique_ptr<Gui> createRISCOSGui(unsigned long xid, float scale, bool loop, RunResources& r);
627 std::unique_ptr<Gui> createAOS4Gui(unsigned long xid, float scale, bool loop, RunResources& r);
628 std::unique_ptr<Gui> createHaikuGui(unsigned long xid, float scale, bool loop, RunResources& r);
629 std::unique_ptr<Gui> createDumpGui(unsigned long xid, float scale, bool loop, RunResources& r);
632 } // end of gnash namespace
634 // end of _GUI_H_
635 #endif
637 // Local Variables:
638 // mode: C++
639 // indent-tabs-mode: nil
640 // End: