2009-11-13 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / runtime.h
blob566756708e85274184afa57b0d997402c88cd8fa
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * runtime.h: Core surface.
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
14 #ifndef __RUNTIME_H__
15 #define __RUNTIME_H__
17 #include <gtk/gtkwidget.h>
18 #include <cairo.h>
20 #include "point.h"
21 #include "uielement.h"
22 #include "dependencyobject.h"
23 #include "dirty.h"
24 #include "value.h"
25 #include "type.h"
26 #include "list.h"
27 #include "error.h"
28 #include "window.h"
30 #define MAXIMUM_CACHE_SIZE 6000000
32 #define FRONT_TO_BACK_STATS 0
34 #define TIMERS 0
35 #define DEBUG_MARKER_KEY 0
36 #if TIMERS
37 #define STARTTIMER(id,str) TimeSpan id##_t_start = get_now(); printf ("timing of '%s' started at %" G_GINT64_FORMAT "\n", str, id##_t_start)
38 #define ENDTIMER(id,str) TimeSpan id##_t_end = get_now(); printf ("timing of '%s' ended at %" G_GINT64_FORMAT " (%f seconds)\n", str, id##_t_end, (double)(id##_t_end - id##_t_start) / 10000000)
39 #else
40 #define STARTTIMER(id,str)
41 #define ENDTIMER(id,str)
42 #endif
44 #if SANITY
45 #define VERIFY_MAIN_THREAD \
46 if (!Surface::InMainThread ()) { \
47 printf ("Moonlight: This method should only be called from the main thread (%s)\n", __PRETTY_FUNCTION__); \
48 print_stack_trace (); \
50 #else
51 #define VERIFY_MAIN_THREAD
52 #endif
54 enum RuntimeInitFlags {
55 RUNTIME_INIT_PANGO_TEXT_LAYOUT = 1 << 0,
56 // (not used) = 1 << 1,
57 RUNTIME_INIT_MANUAL_TIMESOURCE = 1 << 2,
58 RUNTIME_INIT_DISABLE_AUDIO = 1 << 3,
59 RUNTIME_INIT_SHOW_EXPOSE = 1 << 4,
60 RUNTIME_INIT_SHOW_CLIPPING = 1 << 5,
61 RUNTIME_INIT_SHOW_BOUNDING_BOXES = 1 << 6,
62 RUNTIME_INIT_SHOW_TEXTBOXES = 1 << 7,
63 RUNTIME_INIT_SHOW_FPS = 1 << 8,
64 RUNTIME_INIT_RENDER_FRONT_TO_BACK = 1 << 9,
65 RUNTIME_INIT_SHOW_CACHE_SIZE = 1 << 10,
66 RUNTIME_INIT_FFMPEG_YUV_CONVERTER = 1 << 11,
67 RUNTIME_INIT_USE_SHAPE_CACHE = 1 << 12,
68 RUNTIME_INIT_USE_UPDATE_POSITION = 1 << 13,
69 RUNTIME_INIT_ALLOW_WINDOWLESS = 1 << 14,
70 RUNTIME_INIT_AUDIO_ALSA_MMAP = 1 << 15,
71 RUNTIME_INIT_AUDIO_ALSA_RW = 1 << 16,
72 RUNTIME_INIT_AUDIO_ALSA = 1 << 17,
73 RUNTIME_INIT_AUDIO_PULSE = 1 << 18,
74 RUNTIME_INIT_USE_IDLE_HINT = 1 << 19,
75 RUNTIME_INIT_USE_BACKEND_XLIB = 1 << 20,
76 RUNTIME_INIT_KEEP_MEDIA = 1 << 21,
77 RUNTIME_INIT_ENABLE_MS_CODECS = 1 << 22,
78 RUNTIME_INIT_DISABLE_FFMPEG_CODECS = 1 << 23,
79 RUNTIME_INIT_ALL_IMAGE_FORMATS = 1 << 24,
80 RUNTIME_INIT_CREATE_ROOT_DOMAIN = 1 << 25,
81 RUNTIME_INIT_DESKTOP_EXTENSIONS = 1 << 26,
84 extern guint32 moonlight_flags;
87 #if DEBUG
88 enum RuntimeDebugFlags {
89 RUNTIME_DEBUG_ALSA = 1 << 0,
90 RUNTIME_DEBUG_AUDIO = 1 << 1,
91 RUNTIME_DEBUG_PULSE = 1 << 2,
92 RUNTIME_DEBUG_HTTPSTREAMING = 1 << 3,
93 RUNTIME_DEBUG_MARKERS = 1 << 4,
94 RUNTIME_DEBUG_MMS = 1 << 5,
95 RUNTIME_DEBUG_MEDIAPLAYER = 1 << 6,
96 RUNTIME_DEBUG_PIPELINE = 1 << 7,
97 RUNTIME_DEBUG_PIPELINE_ERROR = 1 << 8,
98 RUNTIME_DEBUG_FRAMEREADERLOOP = 1 << 9,
99 RUNTIME_DEBUG_FFMPEG = 1 << 10,
100 RUNTIME_DEBUG_UI = 1 << 11,
101 RUNTIME_DEBUG_CODECS = 1 << 12,
102 RUNTIME_DEBUG_DP = 1 << 13,
103 RUNTIME_DEBUG_DOWNLOADER = 1 << 14,
104 RUNTIME_DEBUG_FONT = 1 << 15,
105 RUNTIME_DEBUG_LAYOUT = 1 << 16,
106 RUNTIME_DEBUG_MEDIA = 1 << 17,
107 RUNTIME_DEBUG_MEDIAELEMENT = 1 << 18,
108 RUNTIME_DEBUG_BUFFERING = 1 << 19,
109 RUNTIME_DEBUG_ASF = 1 << 20,
110 RUNTIME_DEBUG_PLAYLIST = 1 << 21,
111 RUNTIME_DEBUG_TEXT = 1 << 22,
112 RUNTIME_DEBUG_XAML = 1 << 23,
113 RUNTIME_DEBUG_DEPLOYMENT = 1 << 24,
114 RUNTIME_DEBUG_MSI = 1 << 25,
115 RUNTIME_DEBUG_MP3 = 1 << 26,
116 RUNTIME_DEBUG_VALUE = 1 << 27,
119 enum RuntimeDebugFlagsExtra {
120 RUNTIME_DEBUG_ALSA_EX = 1 << 0,
121 RUNTIME_DEBUG_AUDIO_EX = 1 << 1,
122 RUNTIME_DEBUG_PULSE_EX = 1 << 2,
123 RUNTIME_DEBUG_MARKERS_EX = 1 << 3,
124 RUNTIME_DEBUG_MEDIAPLAYER_EX = 1 << 4,
125 RUNTIME_DEBUG_MEDIAELEMENT_EX = 1 << 5,
126 RUNTIME_DEBUG_PLAYLIST_EX = 1 << 6,
127 RUNTIME_DEBUG_PIPELINE_EX = 1 << 7,
130 extern guint32 debug_flags_ex;
131 extern guint32 debug_flags;
132 #endif
135 class TimeManager;
136 class Surface;
137 class Downloader;
139 typedef void (* MoonlightFPSReportFunc) (Surface *surface, int nframes, float nsecs, void *user_data);
140 typedef void (* MoonlightCacheReportFunc) (Surface *surface, long size, void *user_data);
141 typedef bool (* MoonlightEventEmitFunc) (UIElement *element, GdkEvent *event);
142 typedef void (* MoonlightExposeHandoffFunc) (Surface *surface, TimeSpan time, void *user_data);
144 /* @Namespace=None,ManagedEvents=Manual */
145 class Surface : public EventObject {
146 public:
147 /* @GenerateCBinding,GeneratePInvoke */
148 Surface (MoonWindow *window);
149 virtual void Dispose ();
151 /* @GenerateCBinding */
152 MoonWindow *GetWindow () { return active_window; }
153 MoonWindow *DetachWindow ();
155 // allows you to redirect painting of the surface to an
156 // arbitrary cairo context.
157 void Paint (cairo_t *ctx, Region *region);
158 /* @GenerateCBinding,GeneratePInvoke */
159 void Paint (cairo_t *ctx, int x, int y, int width, int height);
161 /* @GenerateCBinding,GeneratePInvoke */
162 void Attach (UIElement *toplevel);
164 void AttachLayer (UIElement *layer);
166 void DetachLayer (UIElement *layer);
168 void SetCursor (MouseCursor cursor);
170 void ReleaseMouseCapture (UIElement *capture);
171 bool SetMouseCapture (UIElement *capture);
173 /* @GenerateCBinding,GeneratePInvoke */
174 void Resize (int width, int height);
176 void EmitSourceDownloadComplete ();
177 void EmitSourceDownloadProgressChanged (DownloadProgressEventArgs *args);
178 void EmitError (ErrorEventArgs *args);
179 /* @GenerateCBinding,GeneratePInvoke */
180 void EmitError (int number, int code, const char *message);
182 void EmitLoad ();
184 void SetBackgroundColor (Color *color);
185 /* @GenerateCBinding,GeneratePInvoke */
186 Color *GetBackgroundColor ();
188 int GetFrameCount () { return frames; }
189 void ResetFrameCount () { frames = 0; }
191 virtual void Invalidate (Rect r);
192 virtual void ProcessUpdates ();
194 /* @GenerateCBinding,GeneratePInvoke */
195 UIElement *GetToplevel() { return toplevel; }
196 bool IsTopLevel (UIElement *top);
198 /* @GenerateCBinding,GeneratePInvoke,Version=2.0 */
199 UIElement *GetFocusedElement () { return focused_element; }
201 bool FocusElement (UIElement *element);
203 /* @GenerateCBinding,GeneratePInvoke */
204 bool IsLoaded () { return toplevel != NULL && ticked_after_attach; }
206 /* @GenerateCBinding,GeneratePInvoke */
207 static bool IsVersionSupported (const char *version);
209 const static int ResizeEvent;
210 const static int FullScreenChangeEvent;
211 const static int ErrorEvent;
212 const static int LoadEvent;
213 const static int SourceDownloadProgressChangedEvent;
214 const static int SourceDownloadCompleteEvent;
216 /* @GenerateCBinding,GeneratePInvoke,Version=2.0 */
217 bool GetFullScreen () { return full_screen; }
218 /* @GenerateCBinding,GeneratePInvoke,Version=2.0 */
219 void SetFullScreen (bool value);
221 void SetUserInitiatedEvent (bool value);
223 bool FirstUserInitiatedEvent () { return first_user_initiated_event; }
224 /* @GenerateCBinding,GeneratePInvoke,Version=2.0 */
225 bool IsUserInitiatedEvent () { return user_initiated_event; }
227 const char* GetSourceLocation ();
228 void SetSourceLocation (const char *location);
229 bool FullScreenKeyHandled (GdkEventKey *key);
231 /* @GenerateCBinding,GeneratePInvoke */
232 TimeManager *GetTimeManager () { return time_manager; }
234 void SetDownloaderContext (gpointer context) { downloader_context = context; }
235 gpointer GetDownloaderContext () { return downloader_context; }
237 /* @GenerateCBinding,GeneratePInvoke */
238 Downloader *CreateDownloader ();
239 static Downloader *CreateDownloader (EventObject *obj);
241 void SetFPSReportFunc (MoonlightFPSReportFunc report, void *user_data);
242 void SetCacheReportFunc (MoonlightCacheReportFunc report, void *user_data);
243 void SetExposeHandoffFunc (MoonlightExposeHandoffFunc func, void *user_data);
245 bool VerifyWithCacheSizeCounter (int w, int h);
246 gint64 AddToCacheSizeCounter (int w, int h);
247 void RemoveFromCacheSizeCounter (gint64 size);
249 // called from the plugin if the surface is headed for death.
250 // stops event emission (since the plugin counterparts to xaml
251 // objects will be destroyed)
252 void Zombify ();
254 bool IsZombie () { return zombie; }
256 void DetachDownloaders ();
258 #if FRONT_TO_BACK_STATS
259 int uielements_rendered_front_to_back;
260 int uielements_rendered_back_to_front;
261 #endif
263 #ifdef DEBUG
264 UIElement *debug_selected_element;
265 #endif
267 void PaintToDrawable (GdkDrawable *drawable, GdkVisual *visual, GdkEventExpose *event, int off_x, int off_y, bool transparent, bool clear_transparent);
270 gboolean HandleUIMotion (GdkEventMotion *event);
271 gboolean HandleUICrossing (GdkEventCrossing *event);
272 gboolean HandleUIKeyPress (GdkEventKey *event);
273 gboolean HandleUIKeyRelease (GdkEventKey *event);
274 gboolean HandleUIButtonRelease (GdkEventButton *event);
275 gboolean HandleUIButtonPress (GdkEventButton *event);
276 gboolean HandleUIScroll (GdkEventScroll *event);
277 gboolean HandleUIFocusIn (GdkEventFocus *event);
278 gboolean HandleUIFocusOut (GdkEventFocus *event);
279 void HandleUIWindowAllocation (bool emit_resize);
280 void HandleUIWindowAvailable ();
281 void HandleUIWindowUnavailable ();
282 void HandleUIWindowDestroyed (MoonWindow *window);
284 // bad, but these live in dirty.cpp, not runtime.cpp
285 void AddDirtyElement (UIElement *element, DirtyType dirt);
286 void UpdateLayout ();
287 void RemoveDirtyElement (UIElement *element);
288 bool ProcessDirtyElements ();
289 void PropagateDirtyFlagToChildren (UIElement *element, DirtyType dirt);
291 static bool main_thread_inited;
292 static pthread_t main_thread;
293 /* @GenerateCBinding,GeneratePInvoke */
294 static bool InMainThread () { return (!main_thread_inited || pthread_equal (main_thread, pthread_self ())); }
296 bool needs_measure;
297 bool needs_arrange;
298 protected:
299 // The current window we are drawing to
300 MoonWindow *active_window;
302 virtual ~Surface();
304 private:
305 // are we headed for death?
306 bool zombie;
308 // bad, but these two live in dirty.cpp, not runtime.cpp
309 void ProcessDownDirtyElements ();
310 void ProcessUpDirtyElements ();
312 DirtyLists *down_dirty;
313 DirtyLists *up_dirty;
315 gpointer downloader_context;
316 List *downloaders;
317 static void OnDownloaderDestroyed (EventObject *sender, EventArgs *args, gpointer closure);
319 Color *background_color;
321 // This is the normal-sized window
322 MoonWindow *normal_window;
324 // We set active_window to this whenever we are in fullscreen mode.
325 MoonWindow *fullscreen_window;
327 // We can have multiple top level elements, these are stored as layers
328 HitTestCollection *layers;
330 UIElement *toplevel;
332 // The element holding the keyboard focus, and the one that
333 // held it previously (so we can emit lostfocus events async)
334 UIElement *focused_element;
335 Queue *focus_changed_events;
337 // the list of elements (from most deeply nested to the
338 // toplevel) we've most recently sent a mouse event to.
339 List *input_list;
341 // is the mouse captured? if it is, it'll be by the first element in input_list.
342 UIElement *captured;
343 UIElement *pendingCapture;
344 bool pendingReleaseCapture;
346 // are we currently emitting a mouse event?
347 bool emittingMouseEvent;
349 // the currently shown cursor
350 MouseCursor cursor;
352 // Fullscreen support
353 bool full_screen;
354 Canvas *full_screen_message;
355 char *source_location;
357 Canvas *incomplete_support_message;
359 // True once we have received at least one user initiated event
360 bool first_user_initiated_event;
361 // Should be set to true only while executing MouseLeftButtonDown,
362 // MouseLeftButtonUp, KeyDown, and KeyUp event handlers
363 bool user_initiated_event;
365 void UpdateFullScreen (bool value);
367 TimeManager *time_manager;
368 bool ticked_after_attach;
369 static void tick_after_attach_reached (EventObject *data);
371 int frames;
373 GdkEvent *mouse_event;
375 // Variables for reporting FPS
376 MoonlightFPSReportFunc fps_report;
377 gint64 fps_start;
378 int fps_nframes;
379 void *fps_data;
381 // Variables for reporting cache size
382 MoonlightCacheReportFunc cache_report;
383 gint64 cache_size_in_bytes;
384 int cache_size_ticker;
385 void *cache_data;
386 int cache_size_multiplier;
388 // Expose handoff
389 TimeSpan expose_handoff_last_timespan;
390 MoonlightExposeHandoffFunc expose_handoff;
391 void *expose_handoff_data;
393 void AutoFocus ();
394 static void AutoFocusAsync (EventObject *sender);
396 void Realloc ();
398 void ShowFullScreenMessage ();
399 void HideFullScreenMessage ();
400 static void HideFullScreenMessageCallback (EventObject *sender, EventArgs *args, gpointer closure);
402 void ShowIncompleteSilverlightSupportMessage ();
403 void HideIncompleteSilverlightSupportMessage ();
404 static void HideIncompleteSilverlightSupportMessageCallback (EventObject *sender, EventArgs *args, gpointer closure);
406 void CreateSimilarSurface ();
408 static void render_cb (EventObject *sender, EventArgs *calldata, gpointer closure);
409 static void update_input_cb (EventObject *sender, EventArgs *calldata, gpointer closure);
410 static void widget_destroyed (GtkWidget *w, gpointer data);
412 EventArgs* CreateArgsForEvent (int event_id, GdkEvent *event);
414 List* ElementPathToRoot (UIElement *source);
415 void GenerateFocusChangeEvents();
417 void FindFirstCommonElement (List *l1, int *index1, List *l2, int *index2);
418 bool EmitEventOnList (int event_id, List *element_list, GdkEvent *event, int end_idx);
419 void UpdateCursorFromInputList ();
420 bool HandleMouseEvent (int event_id, bool emit_leave, bool emit_enter, bool force_emit, GdkEvent *event);
421 void PerformCapture (UIElement *capture);
422 void PerformReleaseCapture ();
424 static void toplevel_loaded (EventObject *sender, EventArgs *args, gpointer closure);
425 void ToplevelLoaded (UIElement *element);
428 /* for hit testing */
429 class UIElementNode : public List::Node {
430 public:
431 UIElement *uielement;
433 UIElementNode (UIElement *el);
434 virtual ~UIElementNode ();
437 /* for rendering */
438 typedef void (*RenderFunc) (cairo_t *ctx, UIElement *uielement, Region *region, bool front_to_back);
440 class RenderNode : public List::Node {
441 public:
442 RenderNode (UIElement *el, Region *region, bool render_element, RenderFunc pre, RenderFunc post);
444 void Render (cairo_t *cr);
446 virtual ~RenderNode ();
448 private:
449 UIElement *uielement;
450 Region *region;
451 bool render_element;
452 RenderFunc pre_render;
453 RenderFunc post_render;
457 G_BEGIN_DECLS
459 void runtime_init (const char *platform_dir, guint32 flags);
461 void runtime_init_browser (const char *plugin_dir);
462 /* @GeneratePInvoke */
463 void runtime_init_desktop ();
465 GList *runtime_get_surface_list (void);
467 void runtime_flags_set_manual_timesource (gboolean flag);
468 void runtime_flags_set_show_fps (gboolean flag);
469 void runtime_flags_set_use_shapecache (gboolean flag);
471 void runtime_shutdown (void);
473 G_END_DECLS
475 #endif