diff -Nur audacity-src-1.3.9-orig/src/LabelTrack.cpp audacity-src-1.3.9/src/LabelTrack.cpp
--- audacity-src-1.3.9-orig/src/LabelTrack.cpp 2009-08-31 12:45:38.000000000 +0200
+++ audacity-src-1.3.9/src/LabelTrack.cpp 2009-09-12 14:59:27.000000000 +0200
@@ -57,6 +57,97 @@
#include "Project.h"
#include "commands/CommandManager.h"
+#if defined(__WXGTK__)
+// As of wxGTK 2.8.9, there is a problem in the wxClipboard class that
+// allows recursive event processing. This problem has been corrected
+// by wxWidgets 2.9+. However, this han't made it into a release yet,
+// so we have to work around it.
+//
+// This is done by pulling/merging in some code from wx29 and creating
+// the following class to capture events while accessing the clipboard
+// to prevent the asynchronous clipboard access from causing recursive
+// event processing.
+
+#include <wx/app.h>
+#include <wx/dynarray.h>
+
+#include <gtk/gtk.h>
+
+extern GtkWidget *wxGetRootWindow();
+
+static void main_do_event(GdkEvent *event, wxArrayPtrVoid *queue)
+{
+ switch (event->type)
+ {
+ case GDK_NOTHING:
+ // Ignore it
+ break;
+
+ case GDK_SELECTION_REQUEST:
+ case GDK_SELECTION_NOTIFY:
+ case GDK_SELECTION_CLEAR:
+#if GTK_CHECK_VERSION(2,6,0)
+ case GDK_OWNER_CHANGE:
+#endif
+ // process it now
+ gtk_main_do_event(event);
+ break;
+
+ default:
+ // process it later (but make a copy; the caller will free the event pointer)
+ queue->Add(gdk_event_copy(event));
+ break;
+ }
+
+ // don't allow idle callbacks while we're active
+ wxTheApp->SuspendIdleCallback();
+
+ return;
+}
+
+class CaptureEvents
+{
+ public:
+ CaptureEvents()
+ {
+#if wxUSE_LOG
+ // disable log flushing from here because a call to wxYield() shouldn't
+ // normally result in message boxes popping up &c
+ wxLog::Suspend();
+#endif
+
+ // temporarily replace the global GDK event handler with our function
+ gdk_event_handler_set((GdkEventFunc)main_do_event, &queue, NULL);
+
+ // temporarily suspend idle callbacks
+ wxTheApp->SuspendIdleCallback();
+ }
+
+ virtual ~CaptureEvents()
+ {
+ gdk_event_handler_set((GdkEventFunc)gtk_main_do_event, NULL, NULL);
+
+ // put all unprocessed GDK events back in the queue
+ GdkDisplay* disp = gtk_widget_get_display(wxGetRootWindow());
+ size_t cnt = queue.GetCount();
+ for (size_t i = 0; i < cnt; i++) {
+ GdkEvent* event = (GdkEvent*)queue[i];
+ // NOTE: gdk_display_put_event makes a copy of the event passed to it
+ gdk_display_put_event(disp, event);
+ gdk_event_free(event);
+ }
+
+#if wxUSE_LOG
+ // let the logs be flashed again
+ wxLog::Resume();
+#endif
+ }
+
+ private:
+ wxArrayPtrVoid queue;
+};
+#endif
+
wxFont LabelTrack::msFont;
// static member variables.
@@ -74,13 +165,11 @@
int LabelTrack::mFontHeight=-1;
-
LabelTrack *TrackFactory::NewLabelTrack()
{
return new LabelTrack(mDirManager);
}
-
LabelTrack::LabelTrack(DirManager * projDirManager):
Track(projDirManager),
mbHitCenter(false),
@@ -969,6 +1058,9 @@
// copy data onto clipboard
if (wxTheClipboard->Open()) {
+#if defined(__WXGTK__)
+ CaptureEvents capture;
+#endif
wxTheClipboard->SetData(new wxTextDataObject(data));
wxTheClipboard->Close();
}
@@ -1001,6 +1093,9 @@
// copy the data on clipboard
if (wxTheClipboard->Open()) {
+#if defined(__WXGTK__)
+ CaptureEvents capture;
+#endif
wxTheClipboard->SetData(new wxTextDataObject(data));
wxTheClipboard->Close();
}
@@ -1021,10 +1116,13 @@
wxString right=wxT("");
// if text data is available
- if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
+ if (IsTextClipSupported()) {
if (wxTheClipboard->Open()) {
+#if defined(__WXGTK__)
+ CaptureEvents capture;
+#endif
wxTextDataObject data;
- wxTheClipboard->GetData( data );
+ wxTheClipboard->GetData(data);
wxTheClipboard->Close();
text = data.GetText();
}
@@ -1077,6 +1175,10 @@
/// @return true if the text data is available in the clipboard, false otherwise
bool LabelTrack::IsTextClipSupported()
{
+#if defined(__WXGTK__)
+ CaptureEvents capture;
+#endif
+
return wxTheClipboard->IsSupported(wxDF_TEXT);
}
diff -Nur audacity-src-1.3.9-orig/src/LabelTrack.h audacity-src-1.3.9/src/LabelTrack.h
--- audacity-src-1.3.9-orig/src/LabelTrack.h 2009-08-31 12:45:38.000000000 +0200
+++ audacity-src-1.3.9/src/LabelTrack.h 2009-09-12 14:59:27.000000000 +0200
@@ -129,7 +129,7 @@
bool CutSelectedText();
bool CopySelectedText();
bool PasteSelectedText(double sel0, double sel1);
- bool IsTextClipSupported();
+ static bool IsTextClipSupported();
// methods to set flags
void SetDragXPos(const int d) { mDragXPos = d; };
diff -Nur audacity-src-1.3.9-orig/src/Menus.cpp audacity-src-1.3.9/src/Menus.cpp
--- audacity-src-1.3.9-orig/src/Menus.cpp 2009-08-31 12:45:38.000000000 +0200
+++ audacity-src-1.3.9/src/Menus.cpp 2009-09-12 15:18:22.150741538 +0200
@@ -1359,20 +1359,6 @@
if (lt->IsTextSelected()) {
flags |= CutCopyAvailableFlag;
}
-
- // See AudacityProject::OnUpdateUI() for an explanation
- if (mInIdle) {
- if (lt->IsTextClipSupported()) {
- flags |= TextClipFlag;
- mTextClipFlag = TextClipFlag;
- }
- else {
- mTextClipFlag = 0;
- }
- }
- else {
- flags |= mTextClipFlag;
- }
}
else if (t->GetKind() == Track::Wave) {
flags |= WaveTracksExistFlag;
@@ -1422,6 +1408,9 @@
if (GetZoom() > gMinZoom && (flags & TracksExistFlag))
flags |= ZoomOutAvailableFlag;
+ if ((flags & LabelTracksExistFlag) && LabelTrack::IsTextClipSupported())
+ flags |= TextClipFlag;
+
flags |= GetFocusedFrame();
if (IsPlayRegionLocked())
diff -Nur audacity-src-1.3.9-orig/src/Project.cpp audacity-src-1.3.9/src/Project.cpp
--- audacity-src-1.3.9-orig/src/Project.cpp 2009-08-31 12:45:38.000000000 +0200
+++ audacity-src-1.3.9/src/Project.cpp 2009-09-12 15:18:29.746745064 +0200
@@ -653,13 +653,12 @@
const wxSize & size)
: wxFrame(parent, id, wxT("Audacity"), pos, size),
mLastPlayMode(normalPlay),
+ mFreqWindow(NULL),
mRate((double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), AudioIO::GetOptimalSupportedSampleRate())),
mDefaultFormat((sampleFormat) gPrefs->
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample)),
mSnapTo(0),
mDirty(false),
- mInIdle(false),
- mTextClipFlag(0),
mTrackPanel(NULL),
mTrackFactory(NULL),
mAutoScrolling(false),
@@ -689,8 +688,7 @@
mWantSaveCompressed(false),
mLastEffect(NULL),
mLastEffectType(0),
- mLastEffectDesc(_("Repeat Last Effect")),
- mFreqWindow(NULL)
+ mLastEffectDesc(_("Repeat Last Effect"))
{
int widths[] = {-1, 130};
mStatusBar = CreateStatusBar(2);
@@ -1644,19 +1642,7 @@
void AudacityProject::OnUpdateUI(wxUpdateUIEvent & event)
{
- // As of wxGTK 2.8.9, there is a problem in the wxClipboard class that
- // allows recursive event processing. This problem has been corrected
- // by wxWidgets changeset #45180. However, this han't made it into a
- // release yet, so we have to work around it.
- //
- // This is done by only checking the wxClipboard contents during an idle
- // event, thus preventing possible recursion during other event processing.
- //
- mInIdle = true;
-
UpdateMenus();
-
- mInIdle = false;
}
void AudacityProject::OnActivate(wxActivateEvent & event)
diff -Nur audacity-src-1.3.9-orig/src/Project.h audacity-src-1.3.9/src/Project.h
--- audacity-src-1.3.9-orig/src/Project.h 2009-08-31 12:45:38.000000000 +0200
+++ audacity-src-1.3.9/src/Project.h 2009-09-12 15:18:26.812745135 +0200
@@ -431,10 +431,6 @@
wxUint32 mLastFlags;
- // see AudacityProject::OnUpdateUI() for explanation of next two
- bool mInIdle;
- wxUint32 mTextClipFlag;
-
// Window elements
wxTimer *mTimer;