/* * A Bedrock Platform-Independent Implementation * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/gui/detail/bedrock_pi.cpp */ #include #include PLATFORM_SPEC_HPP #include #include #include #include #include #include #include #include #include #include #include namespace nana { //class event_arg event_arg::~event_arg(){} void event_arg::stop_propagation() const { stop_propagation_ = true; } bool event_arg::propagation_stopped() const { return stop_propagation_; } //end class event_arg namespace detail { void events_operation_register(event_handle evt) { bedrock::instance().evt_operation.register_evt(evt); } void events_operation_cancel(event_handle evt) { bedrock::instance().evt_operation.cancel(evt); } void bedrock::event_expose(core_window_t * wd, bool exposed) { if (nullptr == wd) return; wd->visible = exposed; arg_expose arg; arg.exposed = exposed; arg.window_handle = reinterpret_cast(wd); if (emit(event_code::expose, wd, arg, false, get_thread_context())) { if (!exposed) { if (category::flags::root != wd->other.category) { //If the wd->parent is a lite_widget then find a parent until it is not a lite_widget wd = wd->parent; while (category::flags::lite_widget == wd->other.category) wd = wd->parent; } else if (category::flags::frame == wd->other.category) wd = wd_manager.find_window(wd->root, wd->pos_root.x, wd->pos_root.y); } wd_manager.refresh_tree(wd); wd_manager.map(wd, false); } } void bedrock::event_move(core_window_t* wd, int x, int y) { if (wd) { arg_move arg; arg.window_handle = reinterpret_cast(wd); arg.x = x; arg.y = y; if (emit(event_code::move, wd, arg, false, get_thread_context())) wd_manager.update(wd, true, true); } } bool bedrock::event_msleave(core_window_t* hovered) { if (wd_manager.available(hovered) && hovered->flags.enabled) { hovered->flags.action = mouse_action::normal; arg_mouse arg; arg.evt_code = event_code::mouse_leave; arg.window_handle = reinterpret_cast(hovered); arg.pos.x = arg.pos.y = 0; arg.left_button = arg.right_button = arg.mid_button = false; arg.ctrl = arg.shift = false; emit(event_code::mouse_leave, hovered, arg, true, get_thread_context()); return true; } return false; } void bedrock::update_cursor(core_window_t * wd) { internal_scope_guard isg; if (wd_manager.available(wd)) { auto * thrd = get_thread_context(wd->thread_id); if (nullptr == thrd) return; auto pos = native_interface::cursor_position(); auto native_handle = native_interface::find_window(pos.x, pos.y); if (!native_handle) return; native_interface::calc_window_point(native_handle, pos); if (wd != wd_manager.find_window(native_handle, pos.x, pos.y)) return; set_cursor(wd, wd->predef_cursor, thrd); } } widget_colors& bedrock::get_scheme_template(scheme_factory_base&& factory) { return pi_data_->scheme.scheme_template(std::move(factory)); } std::unique_ptr bedrock::make_scheme(scheme_factory_base&& factory) { return pi_data_->scheme.create(std::move(factory)); } 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: case event_code::dbl_click: case event_code::mouse_enter: case event_code::mouse_move: case event_code::mouse_leave: case event_code::mouse_down: case event_code::mouse_up: { auto arg = dynamic_cast(&event_arg); if (nullptr == arg) return; void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&); ::nana::basic_event* evt_addr; switch (evt_code) { case event_code::click: drawer_event_fn = &drawer::click; evt_addr = &evts_ptr->click; break; case event_code::dbl_click: drawer_event_fn = &drawer::dbl_click; evt_addr = &evts_ptr->dbl_click; break; case event_code::mouse_enter: drawer_event_fn = &drawer::mouse_enter; evt_addr = &evts_ptr->mouse_enter; break; case event_code::mouse_move: drawer_event_fn = &drawer::mouse_move; evt_addr = &evts_ptr->mouse_move; break; case event_code::mouse_leave: drawer_event_fn = &drawer::mouse_leave; evt_addr = &evts_ptr->mouse_leave; break; case event_code::mouse_down: drawer_event_fn = &drawer::mouse_down; evt_addr = &evts_ptr->mouse_down; break; case event_code::mouse_up: drawer_event_fn = &drawer::mouse_up; evt_addr = &evts_ptr->mouse_up; break; default: throw std::runtime_error("Invalid mouse event code"); } (wd->drawer.*drawer_event_fn)(*arg); if (!draw_only) evt_addr->emit(*arg); break; } case event_code::mouse_wheel: { auto arg = dynamic_cast(&event_arg); if (arg) { wd->drawer.mouse_wheel(*arg); if (!draw_only) evts_ptr->mouse_wheel.emit(*arg); } break; } case event_code::key_press: case event_code::key_char: case event_code::key_release: case event_code::shortkey: { auto arg = dynamic_cast(&event_arg); if (nullptr == arg) return; void(::nana::detail::drawer::*drawer_event_fn)(const arg_keyboard&); ::nana::basic_event* evt_addr; switch (evt_code) { case event_code::key_press: drawer_event_fn = &drawer::key_press; evt_addr = &evts_ptr->key_press; break; case event_code::key_char: drawer_event_fn = &drawer::key_char; evt_addr = &evts_ptr->key_char; break; case event_code::key_release: drawer_event_fn = &drawer::key_release; evt_addr = &evts_ptr->key_release; break; case event_code::shortkey: drawer_event_fn = &drawer::shortkey; evt_addr = &evts_ptr->shortkey; break; default: throw std::runtime_error("Invalid keyboard event code"); } (wd->drawer.*drawer_event_fn)(*arg); if (!draw_only) evt_addr->emit(*arg); break; } case event_code::expose: if (!draw_only) { auto arg = dynamic_cast(&event_arg); if (arg) evts_ptr->expose.emit(*arg); } break; case event_code::focus: { auto arg = dynamic_cast(&event_arg); if (arg) { wd->drawer.focus(*arg); if (!draw_only) evts_ptr->focus.emit(*arg); } break; } case event_code::move: { auto arg = dynamic_cast(&event_arg); if (arg) { wd->drawer.move(*arg); if (!draw_only) evts_ptr->move.emit(*arg); } break; } case event_code::resizing: { auto arg = dynamic_cast(&event_arg); if (arg) { wd->drawer.resizing(*arg); if (!draw_only) evts_ptr->resizing.emit(*arg); } break; } case event_code::resized: { auto arg = dynamic_cast(&event_arg); if (arg) { wd->drawer.resized(*arg); if (!draw_only) evts_ptr->resized.emit(*arg); } break; } case event_code::unload: if (!draw_only) { auto arg = dynamic_cast(&event_arg); if (arg && (wd->other.category == category::flags::root)) { auto evt_root = dynamic_cast(evts_ptr); if (evt_root) evt_root->unload.emit(*arg); } } break; case event_code::destroy: if (!draw_only) { auto arg = dynamic_cast(&event_arg); if (arg) evts_ptr->destroy.emit(*arg); } break; default: throw std::runtime_error("Invalid event code"); } } void bedrock::_m_except_handler() { std::vector v; wd_manager.all_handles(v); if (v.size()) { std::vector roots; native_window_type root = nullptr; unsigned tid = nana::system::this_thread_id(); for (auto wd : v) { if ((wd->thread_id == tid) && (wd->root != root)) { root = wd->root; if (roots.cend() == std::find(roots.cbegin(), roots.cend(), root)) roots.push_back(root); } } for (auto i : roots) interface_type::close_window(i); } } }//end namespace detail }//end namespace nana