From 035474e17c9a5adc5a06629754573070bba42617 Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Mon, 26 May 2008 19:03:31 -0500 Subject: [PATCH] Clean up a number of focus/event handling problems. --- FL/event_name.C | 52 ++++++++++++++++++++++++++++++++++++ FL/event_name.H | 20 ++++++++++++++ FL/test_press.C | 37 +++++++++++++++++++++++++ FL/test_press.H | 20 ++++++++++++++ Timeline/Annotation_Region.C | 16 ++++++----- Timeline/Audio_Region.C | 9 ++++--- Timeline/Sequence.C | 35 +++++++++++++++++++++--- Timeline/Sequence.H | 3 +++ Timeline/Sequence_Region.C | 8 +++--- Timeline/Sequence_Widget.C | 18 ++++++++----- Timeline/Timeline.C | 21 ++++++++++----- Timeline/Track.C | 11 +++++++- 12 files changed, 219 insertions(+), 31 deletions(-) create mode 100644 FL/event_name.C create mode 100644 FL/event_name.H create mode 100644 FL/test_press.C create mode 100644 FL/test_press.H diff --git a/FL/event_name.C b/FL/event_name.C new file mode 100644 index 0000000..d53ab98 --- /dev/null +++ b/FL/event_name.C @@ -0,0 +1,52 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +static const char *event_names[] = +{ + "FL_NO_EVENT", + "FL_PUSH", + "FL_RELEASE", + "FL_ENTER", + "FL_LEAVE", + "FL_DRAG", + "FL_FOCUS", + "FL_UNFOCUS", + "FL_KEYDOWN", + "FL_KEYUP", + "FL_CLOSE", + "FL_MOVE", + "FL_SHORTCUT", + "FL_DEACTIVATE", + "FL_ACTIVATE", + "FL_HIDE", + "FL_SHOW", + "FL_PASTE", + "FL_SELECTIONCLEAR", + "FL_MOUSEWHEEL", + "FL_DND_ENTER", + "FL_DND_DRAG", + "FL_DND_LEAVE", + "FL_DND_RELEASE", +}; + +const char * +event_name ( int m ) +{ + return event_names[ m ]; +} diff --git a/FL/event_name.H b/FL/event_name.H new file mode 100644 index 0000000..28d58d6 --- /dev/null +++ b/FL/event_name.H @@ -0,0 +1,20 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +const char *event_name ( int m ); diff --git a/FL/test_press.C b/FL/test_press.C new file mode 100644 index 0000000..6fddf70 --- /dev/null +++ b/FL/test_press.C @@ -0,0 +1,37 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +/* Fl::test_shortcut() is broken for use in FL_PUSH handlers etc, + * because it relies on Fl::event_text(), which isn't cleared as it + * should be--and there's no official way to clear it. Therefore, we + * provide a test_press() function instead, which, unlike + * test_shortcut(), does not treat a missing FL_SHIFT as "don't care". */ + +#include + +int +test_press ( unsigned long e ) +{ + ((char *)Fl::event_text())[0] = '\0'; + + if ( ! ( e & FL_SHIFT ) ) + return Fl::test_shortcut( e ) && ! Fl::event_shift(); + else + return Fl::test_shortcut( e ); +} diff --git a/FL/test_press.H b/FL/test_press.H new file mode 100644 index 0000000..3b0fe55 --- /dev/null +++ b/FL/test_press.H @@ -0,0 +1,20 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +int test_press ( unsigned long e ); diff --git a/Timeline/Annotation_Region.C b/Timeline/Annotation_Region.C index e4edb41..3ad5a88 100644 --- a/Timeline/Annotation_Region.C +++ b/Timeline/Annotation_Region.C @@ -90,22 +90,26 @@ Annotation_Region::draw ( void ) } #include "FL/Fl_Text_Edit_Window.H" +#include "FL/test_press.H" int Annotation_Region::handle ( int m ) { Logger _log( this ); - if ( m == FL_PUSH && Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() ) + if ( m == FL_PUSH ) { - char *s = fl_text_edit( "Annotation text:", "&Save", name() ); + if ( test_press( FL_BUTTON3 ) ) + { + char *s = fl_text_edit( "Annotation text:", "&Save", name() ); - if ( s ) - name( s ); + if ( s ) + name( s ); - free( s ); + free( s ); - return 0; + return 0; + } } int r = Sequence_Region::handle( m ); diff --git a/Timeline/Audio_Region.C b/Timeline/Audio_Region.C index 253c7e3..b2ab7dc 100644 --- a/Timeline/Audio_Region.C +++ b/Timeline/Audio_Region.C @@ -193,6 +193,7 @@ Audio_Region::source_name ( void ) const } #include +#include "FL/test_press.H" int Audio_Region::handle ( int m ) @@ -244,7 +245,7 @@ Audio_Region::handle ( int m ) case FL_PUSH: { /* splitting */ - if ( Fl::test_shortcut( FL_BUTTON2 | FL_SHIFT ) ) + if ( test_press( FL_BUTTON2 | FL_SHIFT ) ) { /* split */ if ( ! copied ) @@ -272,13 +273,13 @@ Audio_Region::handle ( int m ) /* for panning */ os = _r->offset; - if ( Fl::test_shortcut( FL_BUTTON2 | FL_CTRL ) && ! Fl::event_shift() ) + if ( test_press( FL_BUTTON2 | FL_CTRL ) ) { normalize(); redraw(); return 1; } - else if ( Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() ) + else if ( test_press( FL_BUTTON3 ) ) { /* context menu */ @@ -344,7 +345,7 @@ Audio_Region::handle ( int m ) _log.hold(); } - if ( Fl::test_shortcut( FL_BUTTON1 | FL_SHIFT | FL_CTRL ) ) + if ( test_press( FL_BUTTON1 | FL_SHIFT | FL_CTRL ) ) { /* panning */ int d = (ox + X) - x(); diff --git a/Timeline/Sequence.C b/Timeline/Sequence.C index 4f06472..950ddb2 100644 --- a/Timeline/Sequence.C +++ b/Timeline/Sequence.C @@ -273,17 +273,29 @@ Sequence::snap ( Sequence_Widget *r ) r->start( f ); } +#include "FL/event_name.H" + int Sequence::handle ( int m ) { + +/* if ( m != FL_NO_EVENT ) */ +/* DMESSAGE( "%s", event_name( m ) ); */ + switch ( m ) { + case FL_NO_EVENT: + /* garbage from overlay window */ + return 0; case FL_FOCUS: case FL_UNFOCUS: + Fl_Widget::handle( m ); + redraw(); return 1; case FL_LEAVE: // DMESSAGE( "leave" ); fl_cursor( FL_CURSOR_DEFAULT ); + Fl_Widget::handle( m ); return 1; case FL_DND_DRAG: return 1; @@ -306,6 +318,8 @@ Sequence::handle ( int m ) if ( ! event_widget() ) fl_cursor( cursor() ); + Fl_Widget::handle( m ); + return 1; case FL_DND_ENTER: case FL_DND_LEAVE: @@ -319,29 +333,41 @@ Sequence::handle ( int m ) { if ( Sequence_Widget::belowmouse() ) Sequence_Widget::belowmouse()->handle( FL_LEAVE ); + Sequence_Widget::belowmouse( r ); if ( r ) r->handle( FL_ENTER ); } - return 0; + return 1; } default: { Sequence_Widget *r = Sequence_Widget::pushed() ? Sequence_Widget::pushed() : event_widget(); +/* if ( this == Fl::focus() ) */ +/* DMESSAGE( "Sequence widget = %p", r ); */ + if ( r ) { int retval = r->dispatch( m ); +/* DMESSAGE( "retval = %d", retval ); */ + + if ( m == FL_PUSH ) + take_focus(); + if ( retval ) { if ( m == FL_PUSH ) { - take_focus(); + if ( Sequence_Widget::pushed() ) + Sequence_Widget::pushed()->handle( FL_UNFOCUS ); Sequence_Widget::pushed( r ); + + r->handle( FL_FOCUS ); } else if ( m == FL_RELEASE ) Sequence_Widget::pushed( NULL ); @@ -368,7 +394,10 @@ Sequence::handle ( int m ) Loggable::block_end(); - return retval; + if ( m == FL_PUSH ) + return 1; + else + return retval; } else return Fl_Widget::handle( m ); diff --git a/Timeline/Sequence.H b/Timeline/Sequence.H index b14be15..0b1a0e6 100644 --- a/Timeline/Sequence.H +++ b/Timeline/Sequence.H @@ -103,6 +103,9 @@ public: void remove_selected ( void ); + Fl_Color color ( void ) const { return this == Fl::focus() ? fl_color_average( FL_FOREGROUND_COLOR, Fl_Widget::color(), 0.24f ) : Fl_Widget::color(); } + void color ( Fl_Color v ) { Fl_Widget::color( v ); } + const std::list widgets ( void ) const { return _widgets; } void queue_delete ( Sequence_Widget *r ) diff --git a/Timeline/Sequence_Region.C b/Timeline/Sequence_Region.C index 6e7cad6..1f029c3 100644 --- a/Timeline/Sequence_Region.C +++ b/Timeline/Sequence_Region.C @@ -127,7 +127,7 @@ Sequence_Region::trim ( enum trim_e t, int X ) } } - +#include "FL/test_press.H" int Sequence_Region::handle ( int m ) @@ -168,7 +168,7 @@ Sequence_Region::handle ( int m ) fl_cursor( FL_CURSOR_WE ); return 1; } - else if ( Fl::test_shortcut( FL_BUTTON2 ) && ! Fl::event_shift() ) + else if ( test_press( FL_BUTTON2 ) ) { if ( Sequence_Widget::current() == this ) { @@ -181,7 +181,7 @@ Sequence_Region::handle ( int m ) redraw(); return 1; } - else if ( Fl::test_shortcut( FL_CTRL + FL_BUTTON1 ) && ! Fl::event_shift() ) + else if ( test_press( FL_CTRL + FL_BUTTON1 ) ) { /* duplication */ fl_cursor( FL_CURSOR_MOVE ); @@ -233,7 +233,7 @@ Sequence_Region::handle ( int m ) return 1; } } - else if ( Fl::test_shortcut( FL_BUTTON1 ) && ! Fl::event_shift() && ! selected() ) + else if ( test_press( FL_BUTTON1 ) && ! selected() ) { /* track jumping */ if ( Y > y() + h() || Y < y() ) diff --git a/Timeline/Sequence_Widget.C b/Timeline/Sequence_Widget.C index 509717c..a287976 100644 --- a/Timeline/Sequence_Widget.C +++ b/Timeline/Sequence_Widget.C @@ -279,6 +279,8 @@ Sequence_Widget::draw_box ( void ) } +#include "FL/test_press.H" + /* base hanlde just does basic dragging */ int Sequence_Widget::handle ( int m ) @@ -288,7 +290,6 @@ Sequence_Widget::handle ( int m ) Logger _log( this ); - switch ( m ) { case FL_ENTER: @@ -301,13 +302,13 @@ Sequence_Widget::handle ( int m ) case FL_PUSH: { /* deletion */ - if ( Fl::test_shortcut( FL_CTRL + FL_BUTTON3 ) && ! Fl::event_shift() ) + if ( test_press( FL_BUTTON3 + FL_CTRL ) ) { redraw(); sequence()->queue_delete( this ); return 1; } - else if ( Fl::test_shortcut( FL_BUTTON1 ) && ! Fl::event_shift() ) + else if ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) ) { fl_cursor( FL_CURSOR_MOVE ); @@ -318,6 +319,7 @@ Sequence_Widget::handle ( int m ) return 0; } case FL_RELEASE: + if ( _drag ) { end_drag(); @@ -329,17 +331,16 @@ Sequence_Widget::handle ( int m ) return 1; case FL_DRAG: { + Fl::event_key( 0 ); + if ( ! _drag ) { begin_drag ( Drag( x() - X, y() - Y, x_to_offset( X ) ) ); _log.hold(); } - if ( ( Fl::test_shortcut( FL_BUTTON1 + FL_CTRL ) || - Fl::test_shortcut( FL_BUTTON1 ) ) && ! Fl::event_shift() ) + else if ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) ) { -// fl_cursor( FL_CURSOR_MOVE ); - redraw(); const nframes_t of = timeline->x_to_offset( X ); @@ -382,7 +383,10 @@ Sequence_Widget::handle ( int m ) return 1; } else + { + DMESSAGE( "unknown" ); return 0; + } } default: return 0; diff --git a/Timeline/Timeline.C b/Timeline/Timeline.C index babdc5b..7453ebd 100644 --- a/Timeline/Timeline.C +++ b/Timeline/Timeline.C @@ -947,6 +947,8 @@ Timeline::track_under ( int Y ) return NULL; } +#include "FL/event_name.H" +#include "FL/test_press.H" int Timeline::handle ( int m ) @@ -954,6 +956,12 @@ Timeline::handle ( int m ) static Drag *drag = NULL; static bool range = false; +/* if ( m != FL_NO_EVENT ) */ +/* DMESSAGE( "%s", event_name( m ) ); */ + + + int r = Fl_Overlay_Window::handle( m ); + switch ( m ) { case FL_FOCUS: @@ -993,19 +1001,20 @@ Timeline::handle ( int m ) /* keep scrollbar from eating these. */ return 0; default: - return Fl_Overlay_Window::handle( m ); + return r; } return 0; } default: { - if ( m == FL_PUSH && this != Fl::focus() ) - take_focus(); + +/* if ( m == FL_PUSH ) */ +/* take_focus(); */ //Fl::focus( this ); - int r = Fl_Overlay_Window::handle( m ); +/* r = Fl_Overlay_Window::handle( m ); */ if ( m != FL_RELEASE && r ) return r; @@ -1017,7 +1026,7 @@ Timeline::handle ( int m ) { case FL_PUSH: { - if ( Fl::test_shortcut( FL_BUTTON1 ) && ! Fl::event_shift() ) + if ( test_press( FL_BUTTON1 ) ) { assert( ! drag ); @@ -1027,7 +1036,7 @@ Timeline::handle ( int m ) return 1; } - else if ( Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() ) + else if ( test_press( FL_BUTTON3 ) ) { const Fl_Menu_Item *r = menu->menu()->popup( X, Y, "Timeline" ); if ( r ) diff --git a/Timeline/Track.C b/Timeline/Track.C index c848af3..0d75d5e 100644 --- a/Timeline/Track.C +++ b/Timeline/Track.C @@ -470,9 +470,16 @@ Track::draw ( void ) Fl_Group::draw(); } +#include "FL/event_name.H" +#include "FL/test_press.H" + int Track::handle ( int m ) { + +/* if ( m != FL_NO_EVENT ) */ +/* DMESSAGE( "%s", event_name( m ) ); */ + switch ( m ) { case FL_MOUSEWHEEL: @@ -493,6 +500,8 @@ Track::handle ( int m ) } case FL_PUSH: { + Fl::event_key( 0 ); + Logger log( this ); int X = Fl::event_x(); @@ -501,7 +510,7 @@ Track::handle ( int m ) if ( Fl_Group::handle( m ) ) return 1; - if ( Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() && X < Track::width() ) + if ( test_press( FL_BUTTON3 ) && X < Track::width() ) { int c = output.size();