fix a crash that caused by double-delete of a event handler

This commit is contained in:
Jinhao
2015-05-01 16:29:51 +08:00
parent f943673d3d
commit a64354900c
9 changed files with 144 additions and 102 deletions

View File

@@ -356,7 +356,6 @@ namespace nana
effect.bground_fade_rate = 0;
together.caret = nullptr;
together.attached_events = nullptr;
extra_width = extra_height = 0;
@@ -369,16 +368,15 @@ namespace nana
bool basic_window::set_events(const std::shared_ptr<general_events>& p)
{
if (together.attached_events)
if (together.events_ptr)
return false;
together.events_ptr = p;
together.attached_events = p.get();
return true;
}
general_events * basic_window::get_events() const
{
return together.attached_events;
return together.events_ptr.get();
}
//end struct basic_window
}//end namespace detail

View File

@@ -146,6 +146,9 @@ namespace nana
void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg)
{
auto retain = wd->together.events_ptr;
auto evts_ptr = retain.get();
switch (evt_code)
{
case event_code::click:
@@ -162,35 +165,36 @@ namespace nana
void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&);
::nana::basic_event<arg_mouse>* evt_addr;
switch (evt_code)
{
case event_code::click:
drawer_event_fn = &drawer::click;
evt_addr = &wd->together.attached_events->click;
evt_addr = &evts_ptr->click;
break;
case event_code::dbl_click:
drawer_event_fn = &drawer::dbl_click;
evt_addr = &wd->together.attached_events->dbl_click;
evt_addr = &evts_ptr->dbl_click;
break;
case event_code::mouse_enter:
drawer_event_fn = &drawer::mouse_enter;
evt_addr = &wd->together.attached_events->mouse_enter;
evt_addr = &evts_ptr->mouse_enter;
break;
case event_code::mouse_move:
drawer_event_fn = &drawer::mouse_move;
evt_addr = &wd->together.attached_events->mouse_move;
evt_addr = &evts_ptr->mouse_move;
break;
case event_code::mouse_leave:
drawer_event_fn = &drawer::mouse_leave;
evt_addr = &wd->together.attached_events->mouse_leave;
evt_addr = &evts_ptr->mouse_leave;
break;
case event_code::mouse_down:
drawer_event_fn = &drawer::mouse_down;
evt_addr = &wd->together.attached_events->mouse_down;
evt_addr = &evts_ptr->mouse_down;
break;
case event_code::mouse_up:
drawer_event_fn = &drawer::mouse_up;
evt_addr = &wd->together.attached_events->mouse_up;
evt_addr = &evts_ptr->mouse_up;
break;
default:
throw std::runtime_error("Invalid mouse event code");
@@ -209,7 +213,7 @@ namespace nana
{
wd->drawer.mouse_wheel(*arg);
if (!draw_only)
wd->together.attached_events->mouse_wheel.emit(*arg);
evts_ptr->mouse_wheel.emit(*arg);
}
break;
}
@@ -229,19 +233,19 @@ namespace nana
{
case event_code::key_press:
drawer_event_fn = &drawer::key_press;
evt_addr = &wd->together.attached_events->key_press;
evt_addr = &evts_ptr->key_press;
break;
case event_code::key_char:
drawer_event_fn = &drawer::key_char;
evt_addr = &wd->together.attached_events->key_char;
evt_addr = &evts_ptr->key_char;
break;
case event_code::key_release:
drawer_event_fn = &drawer::key_release;
evt_addr = &wd->together.attached_events->key_release;
evt_addr = &evts_ptr->key_release;
break;
case event_code::shortkey:
drawer_event_fn = &drawer::shortkey;
evt_addr = &wd->together.attached_events->shortkey;
evt_addr = &evts_ptr->shortkey;
break;
default:
throw std::runtime_error("Invalid keyboard event code");
@@ -256,7 +260,7 @@ namespace nana
{
auto arg = dynamic_cast<const arg_expose*>(&event_arg);
if (arg)
wd->together.attached_events->expose.emit(*arg);
evts_ptr->expose.emit(*arg);
}
break;
case event_code::focus:
@@ -266,7 +270,7 @@ namespace nana
{
wd->drawer.focus(*arg);
if (!draw_only)
wd->together.attached_events->focus.emit(*arg);
evts_ptr->focus.emit(*arg);
}
break;
}
@@ -277,7 +281,7 @@ namespace nana
{
wd->drawer.move(*arg);
if (!draw_only)
wd->together.attached_events->move.emit(*arg);
evts_ptr->move.emit(*arg);
}
break;
}
@@ -288,7 +292,7 @@ namespace nana
{
wd->drawer.resizing(*arg);
if (!draw_only)
wd->together.attached_events->resizing.emit(*arg);
evts_ptr->resizing.emit(*arg);
}
break;
}
@@ -299,7 +303,7 @@ namespace nana
{
wd->drawer.resized(*arg);
if (!draw_only)
wd->together.attached_events->resized.emit(*arg);
evts_ptr->resized.emit(*arg);
}
break;
}
@@ -309,9 +313,9 @@ namespace nana
auto arg = dynamic_cast<const arg_unload*>(&event_arg);
if (arg && (wd->other.category == category::flags::root))
{
auto evt_ptr = dynamic_cast<events_root_extension*>(wd->together.attached_events);
if (evt_ptr)
evt_ptr->unload.emit(*arg);
auto evt_root = dynamic_cast<events_root_extension*>(evts_ptr);
if (evt_root)
evt_root->unload.emit(*arg);
}
}
break;
@@ -320,7 +324,7 @@ namespace nana
{
auto arg = dynamic_cast<const arg_destroy*>(&event_arg);
if (arg)
wd->together.attached_events->destroy.emit(*arg);
evts_ptr->destroy.emit(*arg);
}
break;
default:

View File

@@ -583,7 +583,7 @@ namespace detail
delete msg.u.mouse_drop.files;
arg.pos.x = msg.u.mouse_drop.x - msgwd->pos_root.x;
arg.pos.y = msg.u.mouse_drop.y - msgwd->pos_root.y;
msgwd->together.attached_events->mouse_dropfiles.emit(arg);
msgwd->together.events_ptr->mouse_dropfiles.emit(arg);
brock.wd_manager.do_lazy_refresh(msgwd, false);
}
break;
@@ -766,7 +766,7 @@ namespace detail
nana::point mspos{xevent.xbutton.x, xevent.xbutton.y};
while(msgwnd)
{
if(msgwnd->together.attached_events->mouse_wheel.length() != 0)
if(msgwnd->together.events_ptr->mouse_wheel.length() != 0)
{
mspos -= msgwnd->pos_root;
arg_wheel arg;
@@ -810,27 +810,29 @@ namespace detail
{
if(hit)
msgwnd->flags.action = mouse_action::over;
auto retain = msgwnd->together.events_ptr;
auto evt_ptr = retain.get();
auto events_ptr = msgwnd->together.events_ptr;
arg.evt_code = event_code::mouse_up;
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
if(fire_click)
{
arg.evt_code = event_code::click;
msgwnd->together.attached_events->click.emit(arg);
evt_ptr->click.emit(arg);
}
if (brock.wd_manager.available(msgwnd))
{
arg.evt_code = event_code::mouse_up;
msgwnd->together.attached_events->mouse_up.emit(arg);
evt_ptr->mouse_up.emit(arg);
}
}
else if(fire_click)
{
arg.evt_code = event_code::click;
msgwnd->together.attached_events->click.emit(arg);
msgwnd->together.events_ptr->click.emit(arg);
}
brock.wd_manager.do_lazy_refresh(msgwnd, false);
}
@@ -1103,7 +1105,7 @@ namespace detail
arg.window_handle = reinterpret_cast<window>(msgwnd);
brock.get_key_state(arg);
msgwnd->together.attached_events->key_char.emit(arg);
msgwnd->together.events_ptr->key_char.emit(arg);
if(arg.ignore == false && brock.wd_manager.available(msgwnd))
brock.emit_drawer(event_code::key_char, msgwnd, arg, &context);
}

View File

@@ -663,6 +663,7 @@ namespace detail
case WM_SETFOCUS:
case WM_KILLFOCUS:
case WM_PAINT:
case WM_SYSCOMMAND:
case WM_CLOSE:
case WM_MOUSEACTIVATE:
case WM_GETMINMAXINFO:
@@ -851,7 +852,7 @@ namespace detail
case WM_WINDOWPOSCHANGED:
if ((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW) && (!msgwnd->visible))
brock.event_expose(msgwnd, true);
else if((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_HIDEWINDOW) && msgwnd->visible)
else if ((reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_HIDEWINDOW) && msgwnd->visible)
brock.event_expose(msgwnd, false);
def_window_proc = true;
@@ -871,6 +872,7 @@ namespace detail
if (!brock.emit(event_code::focus, focus, arg, true, &context))
brock.wd_manager.set_focus(msgwnd, true);
}
def_window_proc = true;
break;
case WM_KILLFOCUS:
if(msgwnd->other.attribute.root->focus)
@@ -891,10 +893,14 @@ namespace detail
//focus_changed means that during an event procedure if the focus is changed
if(brock.wd_manager.available(msgwnd))
msgwnd->root_widget->other.attribute.root->context.focus_changed = true;
def_window_proc = true;
break;
case WM_MOUSEACTIVATE:
if(msgwnd->flags.take_active == false)
return MA_NOACTIVATE;
def_window_proc = true;
break;
case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK:
pressed_wd = nullptr;
@@ -1011,19 +1017,19 @@ namespace detail
if (fire_click)
{
arg.evt_code = event_code::click;
msgwnd->together.attached_events->click.emit(arg);
retain->click.emit(arg);
}
if (brock.wd_manager.available(msgwnd))
{
arg.evt_code = event_code::mouse_up;
msgwnd->together.attached_events->mouse_up.emit(arg);
retain->mouse_up.emit(arg);
}
}
else if (fire_click)
{
arg.evt_code = event_code::click;
msgwnd->together.attached_events->click.emit(arg);
retain->click.emit(arg);
}
brock.wd_manager.do_lazy_refresh(msgwnd, false);
}
@@ -1114,7 +1120,7 @@ namespace detail
auto evt_wd = scrolled_wd;
while (evt_wd)
{
if (evt_wd->together.attached_events->mouse_wheel.length() != 0)
if (evt_wd->together.events_ptr->mouse_wheel.length() != 0)
{
def_window_proc = false;
nana::point mspos{ scr_pos.x, scr_pos.y };
@@ -1189,7 +1195,7 @@ namespace detail
brock.wd_manager.calc_window_point(msgwnd, dropfiles.pos);
dropfiles.window_handle = reinterpret_cast<window>(msgwnd);
msgwnd->together.attached_events->mouse_dropfiles.emit(dropfiles);
msgwnd->together.events_ptr->mouse_dropfiles.emit(dropfiles);
brock.wd_manager.do_lazy_refresh(msgwnd, false);
}
}
@@ -1419,7 +1425,7 @@ namespace detail
brock.get_key_state(arg);
arg.ignore = false;
msgwnd->together.attached_events->key_char.emit(arg);
msgwnd->together.events_ptr->key_char.emit(arg);
if ((false == arg.ignore) && brock.wd_manager.available(msgwnd))
brock.emit_drawer(event_code::key_char, msgwnd, arg, &context);
@@ -1449,6 +1455,14 @@ namespace detail
brock.delay_restore(2); //Restores while key release
break;
case WM_SYSCOMMAND:
if (SC_TASKLIST == wParam)
{
int debug = 0;
//brock.close_menu_if_focus_other_window()
}
def_window_proc = true;
break;
case WM_CLOSE:
{
arg_unload arg;
@@ -1537,7 +1551,8 @@ namespace detail
impl_->menu.taken_window = wd;
//assigning of a nullptr taken window is to restore the focus of pre taken
if ((!wd) && pre)
//don't restore the focus if pre is a menu.
if ((!wd) && pre && (pre->root != get_menu()))
{
internal_scope_guard lock;
wd_manager.set_focus(pre, false);

View File

@@ -21,7 +21,6 @@
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/effects_renderer.hpp>
#include <stdexcept>
#include <algorithm>
namespace nana
{
@@ -192,7 +191,7 @@ namespace detail
switch(evtid)
{
case event_code::mouse_drop:
wd->flags.dropable = (is_make || (0 != wd->together.attached_events->mouse_dropfiles.length()));
wd->flags.dropable = (is_make || (0 != wd->together.events_ptr->mouse_dropfiles.length()));
break;
default:
break;
@@ -985,11 +984,15 @@ namespace detail
}
else
{
auto i = std::find_if(attr_cap.begin(), attr_cap.end(),
[wd](const std::pair<core_window_t*, bool> & x){ return (x.first == wd);});
for (auto i = attr_cap.begin(), end = attr_cap.end(); i != end; ++i)
{
if (i->first == wd)
{
attr_cap.erase(i);
break;
}
}
if(i != attr_cap.end())
attr_cap.erase(i);
return attr_.capture.window;
}
return wd;

View File

@@ -109,11 +109,11 @@ namespace nana
{
public:
#if defined(NANA_WINDOWS)
timer_core(timer_identifier tmid, const nana::basic_event<arg_elapse>& evt_elapse)
timer_core(timer_identifier tmid, basic_event<arg_elapse>& evt_elapse)
: timer_(tmid), evt_elapse_(evt_elapse)
{}
#else
timer_core(const nana::basic_event<arg_elapse>& evt_elapse)
timer_core(basic_event<arg_elapse>& evt_elapse)
: timer_(this), evt_elapse_(evt_elapse)
{}
#endif
@@ -138,7 +138,7 @@ namespace nana
}
private:
const timer_identifier timer_;
const nana::basic_event<arg_elapse> & evt_elapse_;
nana::basic_event<arg_elapse> & evt_elapse_;
}; //end class timer_core
#if defined(NANA_WINDOWS)