rendered paste bodycommit 27ad88d3c42d28c3da6fa03d35cf3d9532434cafAuthor: Chris Toshok <toshok@gmail.com>Date: Tue Aug 4 19:33:58 2009 -0700 2009-08-04 Chris Toshok <toshok@ximian.com> * popup.cpp (class GenerationClosure): new closure for emiting the Opened and Closed events. (Popup::emit_opened, Popup::emit_closed): pass the generation from the closure to ->Emit. (Popup::OnPropertyChanged): for the tick call, pass a closure that contains the current event generation. * timemanager.h, timemanager.cpp (TimeManager::InvokeTickCalls): factor out the loop for invoking tick calls here and call it from the source tick method. * window-gtk.cpp (MoonWindowGtk::button_press) (MoonWindowGtk::button_release, MoonWindowGtk::scroll) (MoonWindowGtk::motion_notify, MoonWindowGtk::crossing_notify) (MoonWindowGtk::focus_in, MoonWindowGtk::focus_out) (MoonWindowGtk::key_press, MoonWindowGtk::key_release): call TimeManager::InvokeTickCalls from each of these methods before we call the Surface::HandleUI* method. * dependencyobject.h (class EventObject): make a couple of api changes: (AddTickCall*): add an "EventObject* data" parameter. if it's NULL, pass "this", so we have the current behavior. (DoEmit/Emit): add a "starting_generation" optional argument. if it's supplied, we invoke only those handlers with tokens less than the starting_generation (i.e. those handlers that were registered before the event was generated.)diff --git a/src/ChangeLog b/src/ChangeLogindex 28a5010..2e3f59d 100644--- a/src/ChangeLog+++ b/src/ChangeLog@@ -1,3 +1,33 @@+2009-08-04 Chris Toshok <toshok@ximian.com>++ * popup.cpp (class GenerationClosure): new closure for emiting the+ Opened and Closed events.+ (Popup::emit_opened, Popup::emit_closed): pass the generation from+ the closure to ->Emit.+ (Popup::OnPropertyChanged): for the tick call, pass a closure that+ contains the current event generation.++ * timemanager.h, timemanager.cpp (TimeManager::InvokeTickCalls):+ factor out the loop for invoking tick calls here and call it from+ the source tick method.++ * window-gtk.cpp (MoonWindowGtk::button_press)+ (MoonWindowGtk::button_release, MoonWindowGtk::scroll)+ (MoonWindowGtk::motion_notify, MoonWindowGtk::crossing_notify)+ (MoonWindowGtk::focus_in, MoonWindowGtk::focus_out)+ (MoonWindowGtk::key_press, MoonWindowGtk::key_release): call+ TimeManager::InvokeTickCalls from each of these methods before we+ call the Surface::HandleUI* method.++ * dependencyobject.h (class EventObject): make a couple of api+ changes:+ (AddTickCall*): add an "EventObject* data" parameter. if it's+ NULL, pass "this", so we have the current behavior.+ (DoEmit/Emit): add a "starting_generation" optional argument. if+ it's supplied, we invoke only those handlers with tokens less than+ the starting_generation (i.e. those handlers that were registered+ before the event was generated.)+ 2009-08-04 Larry Ewing <lewing@novell.com> * uielement.cpp (DoMeasure): invalidate up the tree morediff --git a/src/dependencyobject.cpp b/src/dependencyobject.cppindex 5fa08bf..33b03ca 100644--- a/src/dependencyobject.cpp+++ b/src/dependencyobject.cpp@@ -201,7 +201,7 @@ EventObject::SetSurfaceUnlock () } void-EventObject::AddTickCallSafe (TickCallHandler handler)+EventObject::AddTickCallSafe (TickCallHandler handler, EventObject *data) { int result; @@ -216,13 +216,13 @@ EventObject::AddTickCallSafe (TickCallHandler handler) return; } - AddTickCallInternal (handler);+ AddTickCallInternal (handler, data); pthread_rwlock_unlock (&surface_lock); } void-EventObject::AddTickCall (TickCallHandler handler)+EventObject::AddTickCall (TickCallHandler handler, EventObject *data) { if (!Surface::InMainThread ()) { g_warning ("EventObject::AddTickCall (): This method must not be called on any other than the main thread! Tick call won't be added.\n");@@ -233,11 +233,11 @@ EventObject::AddTickCall (TickCallHandler handler) return; } - AddTickCallInternal (handler);+ AddTickCallInternal (handler, data); } void-EventObject::AddTickCallInternal (TickCallHandler handler)+EventObject::AddTickCallInternal (TickCallHandler handler, EventObject *data) { Surface *surface; TimeManager *timemanager;@@ -259,7 +259,7 @@ EventObject::AddTickCallInternal (TickCallHandler handler) return; } - timemanager->AddTickCall (handler, this);+ timemanager->AddTickCall (handler, data ? data : this); } Deployment *@@ -723,8 +723,22 @@ EventObject::RemoveMatchingHandlers (int event_id, bool (*predicate)(EventHandle } } +int+EventObject::GetEventGeneration (int event_id)+{+ if (GetType()->GetEventCount() <= 0) {+ g_warning ("adding handler to event with id %d, which has not been registered\n", event_id);+ return -1;+ }+ + if (events == NULL)+ events = new EventLists (GetType ()->GetEventCount ());+ + return events->lists [event_id].current_token;+}+ bool-EventObject::Emit (char *event_name, EventArgs *calldata, bool only_unemitted)+EventObject::Emit (char *event_name, EventArgs *calldata, bool only_unemitted, int starting_generation) { Deployment *deployment = GetDeployment (); if (deployment && deployment->isDead)@@ -762,7 +776,7 @@ EventObject::EmitCallback (gpointer d) } bool-EventObject::Emit (int event_id, EventArgs *calldata, bool only_unemitted)+EventObject::Emit (int event_id, EventArgs *calldata, bool only_unemitted, int starting_generation) { if (IsDisposed ()) return false;@@ -804,7 +818,7 @@ EventObject::Emit (int event_id, EventArgs *calldata, bool only_unemitted) EmitContext* ctx = StartEmit (event_id); - DoEmit (event_id, ctx, calldata, only_unemitted);+ DoEmit (event_id, ctx, calldata, only_unemitted, starting_generation); if (calldata) calldata->unref ();@@ -861,7 +875,7 @@ EventObject::StartEmit (int event_id) } bool-EventObject::DoEmit (int event_id, EmitContext *ctx, EventArgs *calldata, bool only_unemitted)+EventObject::DoEmit (int event_id, EmitContext *ctx, EventArgs *calldata, bool only_unemitted, int starting_generation) { EventClosure *xaml_closure = NULL; @@ -880,7 +894,8 @@ EventObject::DoEmit (int event_id, EmitContext *ctx, EventArgs *calldata, bool o #endif if (closure && closure->func- && (!only_unemitted || closure->emit_count == 0)) {+ && (!only_unemitted || closure->emit_count == 0)+ && (starting_generation == -1 || closure->token < starting_generation)) { closure->func (this, calldata, closure->data); closure->emit_count ++; }diff --git a/src/dependencyobject.h b/src/dependencyobject.hindex 6334eaf..20494e3 100644--- a/src/dependencyobject.h+++ b/src/dependencyobject.h@@ -154,8 +154,8 @@ public: // Only AddTickCallSafe is safe to call on threads other than the main thread, // and only if the type on which it is called overrides SetSurface and surrounds // the call to the base type's SetSurface with SetSurfaceLock/Unlock.- void AddTickCall (TickCallHandler handler);- void AddTickCallSafe (TickCallHandler handler);+ void AddTickCall (TickCallHandler handler, EventObject *data = NULL);+ void AddTickCallSafe (TickCallHandler handler, EventObject *data = NULL); /* @GenerateCBinding,GeneratePInvoke */ void SetObjectType (Type::Kind value) { object_type = value; }@@ -168,7 +168,7 @@ public: void unref_delayed (); EmitContext *StartEmit (int event_id);- bool DoEmit (int event_id, EmitContext *ctx, EventArgs *calldata = NULL, bool only_unemitted = false);+ bool DoEmit (int event_id, EmitContext *ctx, EventArgs *calldata = NULL, bool only_unemitted = false, int starting_generation = -1); void FinishEmit (int event_id, EmitContext *ctx); static gboolean EmitCallback (gpointer d); @@ -201,11 +201,13 @@ protected: // To enable scenarios like Emit ("Event", new EventArgs ()) // Emit will call unref on the calldata.- bool Emit (char *event_name, EventArgs *calldata = NULL, bool only_unemitted = false);- bool Emit (int event_id, EventArgs *calldata = NULL, bool only_unemitted = false);+ bool Emit (char *event_name, EventArgs *calldata = NULL, bool only_unemitted = false, int starting_generation = -1);+ bool Emit (int event_id, EventArgs *calldata = NULL, bool only_unemitted = false, int starting_generation = -1);++ int GetEventGeneration (int event_id); private:- void AddTickCallInternal (TickCallHandler handler);+ void AddTickCallInternal (TickCallHandler handler, EventObject *data = NULL); void Initialize (Deployment *deployment, Type::Kind type); EventLists *events;diff --git a/src/popup.cpp b/src/popup.cppindex 31678fa..c17af8f 100644--- a/src/popup.cpp+++ b/src/popup.cpp@@ -11,16 +11,48 @@ #include "popup.h" #include "runtime.h" +class GenerationClosure : public EventObject {+public:+ GenerationClosure (int generation, Popup *popup)+ {+ this->generation = generation;+ this->popup = popup;++ popup->ref ();+ }++ virtual ~GenerationClosure ()+ {+ popup->unref ();+ }++ int generation;+ Popup *popup;+};++ void Popup::emit_opened (EventObject *sender) {- ((Popup *)sender)->Emit (Popup::OpenedEvent);+ GenerationClosure *closure = (GenerationClosure *)sender;+ Popup * popup = closure->popup;+ int generation = closure->generation;++ closure->unref ();++ popup->Emit (Popup::OpenedEvent, NULL, false, generation); } void Popup::emit_closed (EventObject *sender) {- ((Popup *)sender)->Emit (Popup::ClosedEvent);+ GenerationClosure *closure = (GenerationClosure *)sender;+ Popup * popup = closure->popup;+ int generation = closure->generation;++ closure->unref ();++ popup->Emit (Popup::ClosedEvent, NULL, false, generation); } Popup::Popup ()@@ -62,11 +94,15 @@ Popup::OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error) // in SL. if (args->GetNewValue () && args->GetNewValue ()->AsBool ()) { Show (GetChild ());- AddTickCall (Popup::emit_opened);+ AddTickCall (Popup::emit_opened,+ new GenerationClosure (GetEventGeneration (Popup::OpenedEvent),+ this)); } else { Hide (GetChild ());- AddTickCall (Popup::emit_closed);+ AddTickCall (Popup::emit_closed,+ new GenerationClosure (GetEventGeneration (Popup::ClosedEvent),+ this)); } } else if (args->GetId () == Popup::ChildProperty) { if (args->GetOldValue () && !args->GetOldValue ()->GetIsNull ()) {diff --git a/src/timemanager.cpp b/src/timemanager.cppindex 15c4c58..4b37079 100644--- a/src/timemanager.cpp+++ b/src/timemanager.cpp@@ -181,6 +181,15 @@ TimeManager::InvokeTickCall () return true; } +void+TimeManager::InvokeTickCalls ()+{+ bool remaining_tick_calls = false;+ do {+ remaining_tick_calls = InvokeTickCall ();+ } while (remaining_tick_calls);+}+ guint TimeManager::AddTimeout (gint priority, guint ms_interval, GSourceFunc func, gpointer tick_data) {@@ -360,10 +369,7 @@ TimeManager::SourceTick () #endif if (current_flags & TIME_MANAGER_TICK_CALL) {- bool remaining_tick_calls = false;- do {- remaining_tick_calls = InvokeTickCall ();- } while (remaining_tick_calls);+ InvokeTickCalls (); } if (current_flags & TIME_MANAGER_UPDATE_CLOCKS) {diff --git a/src/timemanager.h b/src/timemanager.hindex 5f4e82c..5957c5d 100644--- a/src/timemanager.h+++ b/src/timemanager.h@@ -45,6 +45,8 @@ public: void NeedRedraw (); void NeedClockTick (); + void InvokeTickCalls ();+ /* @GenerateCBinding, GeneratePInvoke */ guint AddTimeout (gint priority, guint ms_interval, GSourceFunc func, gpointer timeout_data); /* @GenerateCBinding, GeneratePInvoke */diff --git a/src/window-gtk.cpp b/src/window-gtk.cppindex c556347..286b89e 100644--- a/src/window-gtk.cpp+++ b/src/window-gtk.cpp@@ -13,6 +13,7 @@ #include "window-gtk.h" #include "deployment.h"+#include "timemanager.h" MoonWindowGtk::MoonWindowGtk (bool fullscreen, int w, int h, MoonWindow *parent) : MoonWindow (w, h)@@ -424,8 +425,10 @@ MoonWindowGtk::button_press (GtkWidget *widget, GdkEventButton *event, gpointer if (event->button != 1 && event->button != 3) return false; - if (window->surface)+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls(); window->surface->HandleUIButtonPress (event);+ } // If we don't support right clicks (i.e. inside the browser) // return false here@@ -444,8 +447,10 @@ MoonWindowGtk::button_release (GtkWidget *widget, GdkEventButton *event, gpointe Deployment::SetCurrent (window->GetDeployment ()); - if (window->surface)+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls(); window->surface->HandleUIButtonRelease (event);+ } // ignore HandleUIButtonRelease's return value, and always // return true here, or it gets bubbled up to firefox. return true;@@ -458,8 +463,10 @@ MoonWindowGtk::scroll (GtkWidget *widget, GdkEventScroll *event, gpointer data) Deployment::SetCurrent (window->GetDeployment ()); - if (window->surface)+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls(); window->surface->HandleUIScroll (event);+ } // ignore HandleUIScroll's return value, and always // return true here, or it gets bubbled up to firefox. return true;@@ -472,8 +479,10 @@ MoonWindowGtk::motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer Deployment::SetCurrent (window->GetDeployment ()); - if (window->surface)+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls(); window->surface->HandleUIMotion (event);+ } // ignore HandleUIMotion's return value, and always // return true here, or it gets bubbled up to firefox. return true;@@ -486,7 +495,13 @@ MoonWindowGtk::crossing_notify (GtkWidget *widget, GdkEventCrossing *event, gpoi Deployment::SetCurrent (window->GetDeployment ()); - return window->surface ? window->surface->HandleUICrossing (event) : false;+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls();+ window->surface->HandleUICrossing (event);+ return true;+ }++ return false; } gboolean@@ -496,7 +511,13 @@ MoonWindowGtk::focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer user_ Deployment::SetCurrent (window->GetDeployment ()); - return window->surface ? window->surface->HandleUIFocusIn (event) : false;+ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls();+ window->surface->HandleUIFocusIn (event);+ return true;+ }++ return false; } gboolean@@ -506,7 +527,14 @@ MoonWindowGtk::focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer user Deployment::SetCurrent (window->GetDeployment ()); - return window->surface ? window->surface->HandleUIFocusOut (event) : false;++ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls();+ window->surface->HandleUIFocusOut (event);+ return true;+ }++ return false; } gboolean@@ -515,7 +543,14 @@ MoonWindowGtk::key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_d MoonWindowGtk *window = (MoonWindowGtk*)user_data; Deployment::SetCurrent (window->GetDeployment ());- return window->surface ? window->surface->HandleUIKeyPress (event) : false;++ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls();+ window->surface->HandleUIKeyPress (event);+ return true;+ }++ return false; } gboolean@@ -524,7 +559,14 @@ MoonWindowGtk::key_release (GtkWidget *widget, GdkEventKey *event, gpointer user MoonWindowGtk *window = (MoonWindowGtk*)user_data; Deployment::SetCurrent (window->GetDeployment ());- return window->surface ? window->surface->HandleUIKeyRelease (event) : false;++ if (window->surface) {+ window->surface->GetTimeManager()->InvokeTickCalls();+ window->surface->HandleUIKeyRelease (event);+ return true;+ }++ return false; } void