summaryrefslogtreecommitdiff
path: root/src/Fl_Table.cxx
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2011-11-13 02:46:10 +0000
committerGreg Ercolano <erco@seriss.com>2011-11-13 02:46:10 +0000
commitbaca25f9024b2b4872691673facbc4eb76681ad5 (patch)
treea93a84a0c5fc686efa1ecb6245fafa62336a11e9 /src/Fl_Table.cxx
parent3086c07eec8d7b87e4504ef58b95e43f34a84051 (diff)
Fix for problem with posting 'popup menus' during user callback
causing change in row/col selection of Fl_Table_Row. As reported by David Lopez in fltk.general on 11/09/2011, Subject: Popup menu over Fl_Table. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9172 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Table.cxx')
-rw-r--r--src/Fl_Table.cxx70
1 files changed, 43 insertions, 27 deletions
diff --git a/src/Fl_Table.cxx b/src/Fl_Table.cxx
index 0a152d17d..8a163dc5d 100644
--- a/src/Fl_Table.cxx
+++ b/src/Fl_Table.cxx
@@ -708,10 +708,20 @@ int Fl_Table::handle(int event) {
return 1;
}
}
+ // Make snapshots of realtime event states *before* we service user's cb,
+ // which may do things like post popup menus that return with unexpected button states.
+ int _event_button = Fl::event_button();
+ int _event_clicks = Fl::event_clicks();
+ int _event_x = Fl::event_x();
+ int _event_y = Fl::event_y();
+ int _event_key = Fl::event_key();
+ int _event_state = Fl::event_state();
+ Fl_Widget *_focus = Fl::focus();
switch ( event ) {
case FL_PUSH:
- if (Fl::event_button() == 1 && !Fl::event_clicks()) {
- if (Fl::focus() != this) {
+ // Single left-click on table? do user's callback with CONTEXT_TABLE
+ if (_event_button == 1 && !_event_clicks) {
+ if (_focus == this) {
take_focus();
do_callback(CONTEXT_TABLE, -1, -1);
ret = 1;
@@ -726,21 +736,27 @@ int Fl_Table::handle(int event) {
current_col = select_col = -1;
}
}
- // Need this for eg. right click to pop up a menu
+ // A click on table with user's callback defined?
+ // Need this for eg. right click to pop up a menu
+ //
if ( Fl_Widget::callback() && // callback defined?
- resizeflag == RESIZE_NONE ) { // not resizing?
- do_callback(context, R, C); // do callback
+ resizeflag == RESIZE_NONE ) { // not resizing?
+ do_callback(context, R, C); // do callback with context (cell, header, etc)
}
+ // Handle selection if handling a left-click
+ // Use snapshot of _event_button we made before servicing user's cb's
+ // to avoid checking realtime state of buttons which may have changed
+ // during the user's callbacks.
+ //
switch ( context ) {
case CONTEXT_CELL:
// FL_PUSH on a cell?
- ret = 1; // express interest in FL_RELEASE
+ ret = 1; // express interest in FL_RELEASE
break;
case CONTEXT_NONE:
// FL_PUSH on table corner?
- if ( Fl::event_button() == 1 &&
- Fl::event_x() < x() + row_header_width()) {
+ if ( _event_button == 1 && _event_x < x() + row_header_width()) {
current_col = 0;
select_col = cols() - 1;
current_row = 0;
@@ -752,7 +768,7 @@ int Fl_Table::handle(int event) {
case CONTEXT_COL_HEADER:
// FL_PUSH on a column header?
- if ( Fl::event_button() == 1) {
+ if ( _event_button == 1) {
// Resizing? Handle it
if ( resizeflag ) {
// Start resize if left click on column border.
@@ -762,7 +778,7 @@ int Fl_Table::handle(int event) {
//
_resizing_col = ( resizeflag & RESIZE_COL_LEFT ) ? C-1 : C;
_resizing_row = -1;
- _dragging_x = Fl::event_x();
+ _dragging_x = _event_x;
ret = 1;
} else {
// Not resizing? Select the column
@@ -778,7 +794,7 @@ int Fl_Table::handle(int event) {
case CONTEXT_ROW_HEADER:
// FL_PUSH on a row header?
- if ( Fl::event_button() == 1 ) {
+ if ( _event_button == 1 ) {
// Resizing? Handle it
if ( resizeflag ) {
// Start resize if left mouse clicked on row border.
@@ -788,7 +804,7 @@ int Fl_Table::handle(int event) {
//
_resizing_row = ( resizeflag & RESIZE_ROW_ABOVE ) ? R-1 : R;
_resizing_col = -1;
- _dragging_y = Fl::event_y();
+ _dragging_y = _event_y;
ret = 1;
} else {
// Not resizing? Select the row
@@ -821,11 +837,11 @@ int Fl_Table::handle(int event) {
// Don't allow column width smaller than 1.
// Continue to show FL_CURSOR_WE at all times during drag.
//
- int offset = _dragging_x - Fl::event_x();
+ int offset = _dragging_x - _event_x;
int new_w = col_width(_resizing_col) - offset;
if ( new_w < _col_resize_min ) new_w = _col_resize_min;
col_width(_resizing_col, new_w);
- _dragging_x = Fl::event_x();
+ _dragging_x = _event_x;
table_resized();
redraw();
change_cursor(FL_CURSOR_WE);
@@ -841,11 +857,11 @@ int Fl_Table::handle(int event) {
// Don't allow row width smaller than 1.
// Continue to show FL_CURSOR_NS at all times during drag.
//
- int offset = _dragging_y - Fl::event_y();
+ int offset = _dragging_y - _event_y;
int new_h = row_height(_resizing_row) - offset;
if ( new_h < _row_resize_min ) new_h = _row_resize_min;
row_height(_resizing_row, new_h);
- _dragging_y = Fl::event_y();
+ _dragging_y = _event_y;
table_resized();
redraw();
change_cursor(FL_CURSOR_NS);
@@ -854,7 +870,7 @@ int Fl_Table::handle(int event) {
do_callback(CONTEXT_RC_RESIZE, R, C);
}
} else {
- if (Fl::event_button() == 1 &&
+ if (_event_button == 1 &&
_selecting == CONTEXT_CELL &&
context == CONTEXT_CELL) {
if (select_row != R || select_col != C) {
@@ -864,7 +880,7 @@ int Fl_Table::handle(int event) {
select_col = C;
ret = 1;
}
- else if (Fl::event_button() == 1 &&
+ else if (_event_button == 1 &&
_selecting == CONTEXT_ROW_HEADER &&
context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) {
if (select_row != R) {
@@ -873,7 +889,7 @@ int Fl_Table::handle(int event) {
select_row = R;
ret = 1;
}
- else if (Fl::event_button() == 1 &&
+ else if (_event_button == 1 &&
_selecting == CONTEXT_COL_HEADER
&& context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) {
if (select_col != C) {
@@ -885,10 +901,10 @@ int Fl_Table::handle(int event) {
}
// Enable autodrag if not resizing, and mouse has moved off table edge
if ( _resizing_row < 0 && _resizing_col < 0 && _auto_drag == 0 &&
- ( Fl::event_x() > x() + w() - 20 ||
- Fl::event_x() < x() + row_header_width() ||
- Fl::event_y() > y() + h() - 20 ||
- Fl::event_y() < y() + col_header_height()
+ ( _event_x > x() + w() - 20 ||
+ _event_x < x() + row_header_width() ||
+ _event_y > y() + h() - 20 ||
+ _event_y < y() + col_header_height()
) ) {
_start_auto_drag();
}
@@ -903,7 +919,7 @@ int Fl_Table::handle(int event) {
case CONTEXT_TABLE: // release on dead zone
if ( _resizing_col == -1 && // not resizing a column
_resizing_row == -1 && // not resizing a row
- Fl_Widget::callback() && // callback defined
+ Fl_Widget::callback() && // callback defined
when() & FL_WHEN_RELEASE && // on button release
_last_row == R ) { // release on same row PUSHed?
// Need this for eg. left clicking on a cell to select it
@@ -914,7 +930,7 @@ int Fl_Table::handle(int event) {
default:
break;
}
- if ( Fl::event_button() == 1 ) {
+ if ( _event_button == 1 ) {
change_cursor(FL_CURSOR_DEFAULT);
_resizing_col = -1;
_resizing_row = -1;
@@ -964,7 +980,7 @@ int Fl_Table::handle(int event) {
ret = 0;
int is_row = select_row;
int is_col = select_col;
- switch(Fl::event_key()) {
+ switch(_event_key) {
case FL_Home:
ret = move_cursor(0, -1000000);
break;
@@ -990,7 +1006,7 @@ int Fl_Table::handle(int event) {
ret = move_cursor(1, 0);
break;
case FL_Tab:
- if ( Fl::event_state() & FL_SHIFT ) {
+ if ( _event_state & FL_SHIFT ) {
ret = move_cursor(0, -1); // shift-tab -> left
} else {
ret = move_cursor(0, 1); // tab -> right