diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index 789ab5c3..26ca8885 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -77,8 +77,8 @@ namespace nana start_of_headline = 0x1, //Ctrl+A end_of_text = 0x3, //Ctrl+C backspace = 0x8, tab = 0x9, - enter_n = 0xA, enter = 0xD, enter_r = 0xD, alt = 0x12, + enter_n = 0xA, enter = 0xD, enter_r = 0xD, sync_idel = 0x16, //Ctrl+V cancel = 0x18, //Ctrl+X end_of_medium = 0x19, //Ctrl+Y @@ -95,6 +95,8 @@ namespace nana undo = substitute, //System Code for OS + os_shift = 0x10, + os_ctrl = 0x11, os_pageup = 0x21, os_pagedown, os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down, os_insert = 0x2D, os_del , diff --git a/include/nana/gui/msgbox.hpp b/include/nana/gui/msgbox.hpp index 1534c7c7..3bebcf79 100644 --- a/include/nana/gui/msgbox.hpp +++ b/include/nana/gui/msgbox.hpp @@ -140,8 +140,11 @@ namespace nana : public abstract_content { struct implement; + + text(const text&) = delete; + text& operator=(const text&) = delete; public: - text(::nana::string label); + text(::nana::string label, ::nana::string init_text = ::nana::string()); text(::nana::string label, std::vector<::nana::string>); ~text(); diff --git a/source/detail/linux_X11/platform_spec.cpp b/source/detail/linux_X11/platform_spec.cpp index 29a9411e..d2244430 100644 --- a/source/detail/linux_X11/platform_spec.cpp +++ b/source/detail/linux_X11/platform_spec.cpp @@ -733,6 +733,8 @@ namespace detail caret_tag * & addr = caret_holder_.carets[wd]; if(0 == addr) { + ::XSetLocaleModifiers(""); + addr = new caret_tag(wd); is_start_routine = (caret_holder_.carets.size() == 1); addr->input_method = ::XOpenIM(display_, 0, 0, 0); @@ -783,8 +785,10 @@ namespace detail ::XFree(attr); } else - addr->input_context = ::XCreateIC(addr->input_method, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), - XNClientWindow, reinterpret_cast(wd), nullptr); + addr->input_context = ::XCreateIC(addr->input_method, + XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), + XNClientWindow, reinterpret_cast(wd), + XNFocusWindow, reinterpret_cast(wd), nullptr); if(addr->input_context) { @@ -795,6 +799,8 @@ namespace detail XSetWindowAttributes new_attr; new_attr.event_mask = (attr.your_event_mask | addr->input_context_event_mask); ::XChangeWindowAttributes(display_, reinterpret_cast(wd), CWEventMask, &new_attr); + + ::XSetICValues(addr->input_context, XNResetState, XIMPreserveState, nullptr); } ::XFree(preedit_attr); ::XFree(status_attr); @@ -1254,11 +1260,13 @@ namespace detail respond.xclient.data.l[2] = self.atombase_.xdnd_action_copy; } ::XSendEvent(self.display_, self.xdnd_.wd_src, False, NoEventMask, &respond); + ::XFlush(self.display_); if(msg.u.mouse_drop.window) return 1; //Use the packet directly. } } + ::XFlush(self.display_); return 2; } else if(SelectionRequest == evt.type) @@ -1277,7 +1285,7 @@ namespace detail } ::XChangeProperty(self.display_, evt.xselectionrequest.requestor, - evt.xselectionrequest.property, XA_ATOM, sizeof(Atom) * 8, 0, + evt.xselectionrequest.property, XA_ATOM, 32, 0, reinterpret_cast(atoms.size() ? &atoms[0] : 0), static_cast(atoms.size())); } else if(XA_STRING == evt.xselectionrequest.target || self.atombase_.utf8_string == evt.xselectionrequest.target) diff --git a/source/gui/detail/linux_X11/bedrock.cpp b/source/gui/detail/linux_X11/bedrock.cpp index fa51348b..2bcf5715 100644 --- a/source/gui/detail/linux_X11/bedrock.cpp +++ b/source/gui/detail/linux_X11/bedrock.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace nana { @@ -54,10 +55,10 @@ namespace detail int window_count{0}; //The number of windows core_window_t* event_window{nullptr}; bool is_alt_pressed{false}; + bool is_ctrl_pressed{false}; struct platform_detail_tag { - nana::char_t keychar; native_window_type motion_window; nana::point motion_pointer_pos; }platform; @@ -568,6 +569,73 @@ namespace detail if(thrd) thrd->event_window = pre_wd; } + wchar_t os_code_from_keysym(KeySym keysym) + { + switch(keysym) + { + case XK_Alt_L: case XK_Alt_R: + keysym = keyboard::alt; break; + case XK_BackSpace: + keysym = keyboard::backspace; break; + case XK_Tab: + keysym = keyboard::tab; break; + case XK_Escape: + keysym = keyboard::escape; break; + case XK_Return: + keysym = keyboard::enter; break; + case XK_Cancel: + keysym = keyboard::end_of_text; break; //Ctrl+C + case XK_Page_Up: + keysym = keyboard::os_pageup; break; + case XK_Page_Down: + keysym = keyboard::os_pagedown; break; + case XK_Left: case XK_Up: case XK_Right: case XK_Down: + keysym = keyboard::os_arrow_left + (keysym - XK_Left); break; + case XK_Insert: + keysym = keyboard::os_insert; break; + case XK_Delete: + keysym = keyboard::os_del; break; + case XK_Shift_L: case XK_Shift_R: //shift + keysym = keyboard::os_shift; break; + case XK_Control_L: case XK_Control_R: //ctrl + keysym = keyboard::os_ctrl; break; + default: + do + { + //Transfer the keysym for key_press and key_release event to the same behavior with Windows + if('a' <= keysym && keysym <= 'z') + { + keysym = keysym - 'a' + 'A'; + break; + } + //reverts the key + static const char shift_num[]=")!@#$%^&*("; + auto p = std::find(shift_num, shift_num + sizeof shift_num, char(keysym)); + if(p != shift_num + sizeof shift_num) + { + keysym = (p - shift_num + '0'); + break; + } + + switch(keysym) + { + case '~': keysym = '`'; break; + case '_': keysym = '-'; break; + case '+': keysym = '='; break; + case '{': keysym = '['; break; + case '}': keysym = ']'; break; + case '|': keysym = '\\'; break; + case ':': keysym = ';'; break; + case '"': keysym = '\''; break; + case '<': keysym = ','; break; + case '>': keysym = '.'; break; + case '?': keysym = '/'; break; + } + }while(false); + } + return wchar_t(keysym); + } + void window_proc_for_xevent(Display* display, XEvent& xevent) { typedef detail::bedrock::core_window_t core_window_t; @@ -953,40 +1021,13 @@ namespace detail } keybuf[len] = 0; - nana::char_t keychar = 0; + ::nana::char_t os_code = 0; switch(status) { case XLookupKeySym: case XLookupBoth: - switch(keysym) - { - case XK_Alt_L: case XK_Alt_R: - keychar = keyboard::alt; break; - case XK_BackSpace: - keychar = keyboard::backspace; break; - case XK_Tab: - keychar = keyboard::tab; break; - case XK_Escape: - keychar = keyboard::escape; break; - case XK_Return: - keychar = keyboard::enter; break; - case XK_Cancel: - keychar = keyboard::end_of_text;break; //Ctrl+C - case XK_Page_Up: - keychar = keyboard::os_pageup; break; - case XK_Page_Down: - keychar = keyboard::os_pagedown; break; - case XK_Left: case XK_Up: case XK_Right: case XK_Down: - keychar = keyboard::os_arrow_left + (keysym - XK_Left); break; - case XK_Insert: - keychar = keyboard::os_insert; break; - case XK_Delete: - keychar = keyboard::os_del; break; - default: - keychar = keysym; - } - context.platform.keychar = keychar; - if(keychar == keyboard::tab && (false == (msgwnd->flags.tab & detail::tab_type::eating))) //Tab + os_code = os_code_from_keysym(keysym); + if(os_code == keyboard::tab && (false == (msgwnd->flags.tab & detail::tab_type::eating))) //Tab { arg_keyboard argkey; brock.get_key_state(argkey); @@ -997,7 +1038,7 @@ namespace detail brock.wd_manager().do_lazy_refresh(tstop_wd, true); } } - else if(keyboard::alt == keychar) + else if(keyboard::alt == os_code) { context.is_alt_pressed = true; if (brock.whether_keyboard_shortkey() == false) @@ -1010,8 +1051,9 @@ namespace detail arg.evt_code = event_code::key_press; arg.window_handle = reinterpret_cast(msgwnd); arg.ignore = false; - arg.key = static_cast(keychar); + arg.key = os_code; brock.get_key_state(arg); + brock.emit(event_code::key_press, msgwnd, arg, true, &context); msgwnd->root_widget->flags.ignore_menubar_focus = (focused && (brock.focus() != msgwnd)); @@ -1022,25 +1064,19 @@ namespace detail } else { + if(keyboard::os_ctrl == os_code) + context.is_ctrl_pressed = true; + arg_keyboard arg; arg.ignore = false; - arg.key = keychar ? keychar : xevent.xkey.keycode; + arg.key = os_code; arg.evt_code = event_code::key_press; brock.get_key_state(arg); arg.window_handle = reinterpret_cast(msgwnd); + brock.emit(event_code::key_press, msgwnd, arg, true, &context); - if((XLookupKeySym == status) && (brock.wd_manager().available(msgwnd))) - { - //call key_char event if status is XLookupKeySym to avaid calling key_char - //twice, because the status would be equal to XLookupChars if the input method is - //enabled for the window. - arg.ignore = false; - arg.evt_code = event_code::key_char; - brock.emit(event_code::key_char, msgwnd, arg, true, & context); - } - - if(msgwnd->root_widget->other.attribute.root->menubar == msgwnd) + if(brock.wd_manager().available(msgwnd) && (msgwnd->root_widget->other.attribute.root->menubar == msgwnd)) { int cmd = (menu_wd && (keyboard::escape == static_cast(arg.key)) ? 1 : 0 ); brock.delay_restore(cmd); @@ -1090,7 +1126,6 @@ namespace detail arg.evt_code = event_code::key_char; arg.window_handle = reinterpret_cast(msgwnd); brock.get_key_state(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); @@ -1101,6 +1136,7 @@ namespace detail } break; } + brock.wd_manager().do_lazy_refresh(msgwnd, false); if(keybuf != fixbuf) delete [] keybuf; @@ -1109,47 +1145,53 @@ namespace detail break; case KeyRelease: nana::detail::platform_spec::instance().write_keystate(xevent.xkey); - if(context.platform.keychar != keyboard::alt) //Must NOT be an ALT { - msgwnd = brock.focus(); - if(msgwnd) + auto os_code = os_code_from_keysym(::XLookupKeysym(&xevent.xkey, 0)); + if(keyboard::alt != os_code) { - arg_keyboard arg; - arg.evt_code = event_code::key_release; - arg.window_handle = reinterpret_cast(msgwnd); - arg.ignore = false; - arg.key = static_cast(context.platform.keychar); - brock.get_key_state(arg); - brock.emit(event_code::key_release, msgwnd, arg, true, &context); - } + if(0x11 == os_code) + context.is_ctrl_pressed = false; - if (context.platform.keychar < keyboard::os_arrow_left || keyboard::os_arrow_down < context.platform.keychar) - brock.delay_restore(2); //Restores while key release - } - else - { - context.is_alt_pressed = false; - if (brock.set_keyboard_shortkey(false) == false) - { - msgwnd = msgwnd->root_widget->other.attribute.root->menubar; - if (msgwnd) + msgwnd = brock.focus(); + if(msgwnd) { - bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus); - if (set_focus) - brock.wd_manager().set_focus(msgwnd, false); - arg_keyboard arg; arg.evt_code = event_code::key_release; arg.window_handle = reinterpret_cast(msgwnd); arg.ignore = false; - arg.key = static_cast(context.platform.keychar); + arg.key = os_code; brock.get_key_state(arg); brock.emit(event_code::key_release, msgwnd, arg, true, &context); + } - if (!set_focus) + if(os_code < keyboard::os_arrow_left || keyboard::os_arrow_down < os_code) + brock.delay_restore(2); //Restores while key release + } + else + { + context.is_alt_pressed = false; + if (brock.set_keyboard_shortkey(false) == false) + { + msgwnd = msgwnd->root_widget->other.attribute.root->menubar; + if (msgwnd) { - brock.set_menubar_taken(nullptr); - msgwnd->root_widget->flags.ignore_menubar_focus = false; + bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus); + if (set_focus) + brock.wd_manager().set_focus(msgwnd, false); + + arg_keyboard arg; + arg.evt_code = event_code::key_release; + arg.window_handle = reinterpret_cast(msgwnd); + arg.ignore = false; + arg.key = os_code; + brock.get_key_state(arg); + brock.emit(event_code::key_release, msgwnd, arg, true, &context); + + if (!set_focus) + { + brock.set_menubar_taken(nullptr); + msgwnd->root_widget->flags.ignore_menubar_focus = false; + } } } } diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index 44addaa6..a34fdbe2 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -809,23 +809,25 @@ namespace nana std::vector< ::nana::string> options; ::nana::string label_text; + ::nana::string init_text; ::nana::panel dock; ::nana::label label; ::nana::combox combox; ::nana::textbox textbox; }; - inputbox::text::text(::nana::string label) + inputbox::text::text(::nana::string label, ::nana::string init_text) : impl_(new implement) { - impl_->label_text = std::move(label); + impl_->label_text.swap(label); + impl_->init_text.swap(init_text); } inputbox::text::text(::nana::string label, std::vector<::nana::string> options) : impl_(new implement) { impl_->options.swap(options); - impl_->label_text = std::move(label); + impl_->label_text.swap(label); } //Instance for impl_ because implmenet is incomplete type at the point of declaration @@ -833,7 +835,7 @@ namespace nana void inputbox::text::tip_string(std::wstring tip) { - impl_->tip = std::move(tip); + impl_->tip.swap(tip); } void inputbox::text::tip_string(std::string tip_utf8) @@ -877,6 +879,7 @@ namespace nana { impl->textbox.create(impl->dock, rectangle{ static_cast(label_px + 10), 0, 0, 0 }); impl->textbox.tip_string(impl->tip); + impl->textbox.caption(impl->init_text); impl->textbox.mask(impl->mask_character); impl->textbox.multi_lines(false); } diff --git a/source/gui/place.cpp b/source/gui/place.cpp index cc57df39..c31daf36 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1920,7 +1920,13 @@ namespace nana for (auto & child : children) { if (!child->display) + { + auto child_dv = dynamic_cast(child.get()); + if (child_dv) + child_dv->splitter.reset(); + continue; + } auto child_dv = dynamic_cast(child.get()); const bool is_vert = _m_is_vert(child->dir); @@ -1949,6 +1955,8 @@ namespace nana else split = dynamic_cast(child_dv->splitter.get()); } + else + child_dv->splitter.reset(); ::nana::rectangle child_r; double split_range_begin = -1, split_range_end; diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 2b9da143..f8026ce7 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -171,20 +171,6 @@ namespace nana } }; - class dock_page - : public form - { - public: - dock_page(window host, const rectangle& r, const rectangle & tab_r) - : form(host, r, form::appear::bald<>()) - { - tab_form_.reset(new form(handle(), tab_r, form::appear::bald<>())); - - } - private: - std::unique_ptr
tab_form_; - }; - class dockarea : public widget_object { @@ -362,16 +348,23 @@ namespace nana API::capture_window(caption_, false); rectangle r{ pos() + move_pos, size() }; - container_.reset(new form(host_window_, r.pare_off(-1), form::appear::bald<>())); + container_.reset(new form(host_window_, r.pare_off(-1), form::appear::bald())); drawing dw(container_->handle()); dw.draw([](paint::graphics& graph) { graph.rectangle(false, colors::coral); }); + + API::set_parent_window(handle(), container_->handle()); this->move({ 1, 1 }); + container_->events().resized([this](const arg_resized& arg) + { + this->size({arg.width - 2, arg.height - 2}); + }); + container_->show(); API::capture_window(caption_, true); diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 461a734e..6a0ab074 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1421,12 +1421,6 @@ namespace nana{ namespace widgets char_type key = arg.key; switch (key) { -#if 0 - case keyboard::os_arrow_left: move_left(); break; - case keyboard::os_arrow_right: move_right(); break; - case keyboard::os_arrow_up: move_ns(true); break; - case keyboard::os_arrow_down: move_ns(false); break; -#else case keyboard::os_arrow_left: case keyboard::os_arrow_right: case keyboard::os_arrow_up: @@ -1437,7 +1431,6 @@ namespace nana{ namespace widgets case keyboard::os_pagedown: _handle_move_key(arg); break; -#endif case keyboard::os_del: if (this->attr().editable) del(); @@ -2328,6 +2321,9 @@ namespace nana{ namespace widgets void text_editor::_handle_move_key(const arg_keyboard& arg) { + if (arg.shift && (select_.a == select_.b)) + select_.a = select_.b = points_.caret; + bool changed = false; nana::upoint caret = points_.caret; char_t key = arg.key; @@ -2716,6 +2712,7 @@ namespace nana{ namespace widgets auto length = text.size(); textbase_.insert(crtpos, std::move(text)); + crtpos.x += static_cast(length); behavior_->pre_calc_line(crtpos.y, width_pixels()); } diff --git a/source/system/dataexch.cpp b/source/system/dataexch.cpp index b3b54686..1158bb26 100644 --- a/source/system/dataexch.cpp +++ b/source/system/dataexch.cpp @@ -115,10 +115,10 @@ namespace nana{ namespace system{ #else str.reserve(size / sizeof(nana::char_t)); str.append(reinterpret_cast(res), reinterpret_cast(res) + size / sizeof(nana::char_t)); - nana::string::size_type pos = str.find_last_not_of(nana::char_t(0)); +#endif + auto pos = str.find_last_not_of(nana::char_t(0)); if(pos != str.npos) str.erase(pos + 1); -#endif #if defined(NANA_X11) ::XFree(res);