diff --git a/frontend/gtkmm/CodeInput.cc b/frontend/gtkmm/CodeInput.cc index 01bec995ac..04c734d36e 100644 --- a/frontend/gtkmm/CodeInput.cc +++ b/frontend/gtkmm/CodeInput.cc @@ -79,7 +79,7 @@ void CodeInput::init(const Prefs& prefs) edit.set_tabs(tabs); edit.signal_button_press_event().connect(sigc::mem_fun(this, &CodeInput::handle_button_press), false); - edit.get_buffer()->signal_insert().connect(sigc::mem_fun(this, &CodeInput::handle_insert), true); + edit.get_buffer()->signal_insert().connect(sigc::mem_fun(this, &CodeInput::handle_insert), true /* run before default handler */); edit.get_buffer()->signal_erase().connect(sigc::mem_fun(this, &CodeInput::handle_erase), false); if (prefs.highlight) { using namespace std::string_literals; @@ -510,7 +510,8 @@ bool CodeInput::exp_input_tv::on_key_press_event(GdkEventKey* event) // bool is_shift_tab = get_editable() && event->keyval==GDK_KEY_Tab && (event->state&Gdk::SHIFT_MASK); bool is_tab = get_editable() && event->keyval==GDK_KEY_Tab; bool retval=false; - // std::cerr << event->keyval << ", " << event->state << " pressed" << std::endl; + // std::cerr << event->keyval << ", " << event->state << " pressed, focus = " << has_focus() + // << ", editable = " << get_editable() << ", is_shift_return = " << is_shift_return << std::endl; if(!is_shift_return && !is_tab) retval=Gtk::TextView::on_key_press_event(event); @@ -561,6 +562,10 @@ void CodeInput::exp_input_tv::shift_enter_pressed() void CodeInput::exp_input_tv::on_textbuf_change() { + // When a keypress happens, this function gets called first (and for every + // widget which shares the TextBuffer). This feeds through that a change + // was made, but nothing else happens. The next event is the handle_insert + // signal. content_changed(datacell); } @@ -681,6 +686,15 @@ void CodeInput::update_buffer() void CodeInput::handle_insert(const Gtk::TextIter& pos, const Glib::ustring& text, int bytes) { + // If we have two CodeInput widgets which share the same + // TextBuffer, then manually inserting (typing) text into one will + // fire handle_insert on both widgets. So we need to not propagate + // this change if we are not focused. + + if(edit.has_focus()==false) { + return; + } + Glib::RefPtr buf=edit.get_buffer(); // warning: pos contains the cursor pos, and because we get to this handler // _after_ the default handler has run, the cursor will have moved by @@ -693,6 +707,11 @@ void CodeInput::handle_insert(const Gtk::TextIter& pos, const Glib::ustring& tex void CodeInput::handle_erase(const Gtk::TextIter& start, const Gtk::TextIter& end) { + // See handle_insert for the 'focus' logic. + if(edit.has_focus()==false) { + return; + } + //std::cerr << "handle_erase: " << start << ", " << end << std::endl; Glib::RefPtr buf=edit.get_buffer(); int spos = buf->get_slice(buf->begin(), start).bytes(); diff --git a/frontend/gtkmm/NotebookWindow.cc b/frontend/gtkmm/NotebookWindow.cc index 3b7ada8019..3f4f4ed74d 100644 --- a/frontend/gtkmm/NotebookWindow.cc +++ b/frontend/gtkmm/NotebookWindow.cc @@ -220,7 +220,10 @@ NotebookWindow::NotebookWindow(Cadabra *c, bool ro) // View menu actions. actiongroup->add_action( "ViewSplit", sigc::mem_fun(*this, &NotebookWindow::on_view_split) ); - actiongroup->add_action( "ViewClose", sigc::mem_fun(*this, &NotebookWindow::on_view_close) ); + action_view_close = Gio::SimpleAction::create("ViewClose"); + action_view_close->signal_activate().connect( sigc::mem_fun(*this, &NotebookWindow::on_view_close) ); + actiongroup->add_action( action_view_close ); + action_fontsize = actiongroup->add_action_radio_integer( "FontSize", sigc::mem_fun(*this, &NotebookWindow::on_prefs_font_size), prefs.font_step ); @@ -955,6 +958,7 @@ void NotebookWindow::update_title() // std::cerr << "redo_stack.size() = " << redo_stack.size() << std::endl; action_undo->set_enabled( undo_stack.size() > 0 ); action_redo->set_enabled( redo_stack.size() > 0 ); + action_view_close->set_enabled( canvasses.size() > 1 ); } void NotebookWindow::set_statusbar_message(const std::string& message, int line, int col) @@ -1730,7 +1734,6 @@ bool NotebookWindow::cell_content_insert(const std::string& content, int pos, DT if(disable_stacks) return false; unselect_output_cell(); - //std::cerr << "cell_content_insert" << std::endl; std::shared_ptr action = std::make_shared(it->id(), pos, content); queue_action(action); process_todo_queue(); @@ -1770,6 +1773,7 @@ void NotebookWindow::dim_output_cells(DTree::iterator it) bool NotebookWindow::cell_got_focus(DTree::iterator it, int canvas_number) { +// std::cerr << "focus on cell " << &(*it) << " canvas " << canvas_number << std::endl; current_cell=it; current_canvas=canvas_number; @@ -2413,7 +2417,7 @@ void NotebookWindow::on_view_split() canvasses[canvasses.size()-2]->set_position(canvasses[canvasses.size()-2]->get_height()/2.0); } -void NotebookWindow::on_view_close() +void NotebookWindow::on_view_close(const Glib::VariantBase&) { // FIXME: this always removes the last canvas, not the current one. if(canvasses.size()>1) { diff --git a/frontend/gtkmm/NotebookWindow.hh b/frontend/gtkmm/NotebookWindow.hh index 96f993bc17..010e04aca6 100644 --- a/frontend/gtkmm/NotebookWindow.hh +++ b/frontend/gtkmm/NotebookWindow.hh @@ -226,7 +226,7 @@ namespace cadabra { void on_edit_find(); void on_view_split(); - void on_view_close(); + void on_view_close(const Glib::VariantBase&); void on_run_cell(); void on_run_runall(); @@ -322,7 +322,7 @@ namespace cadabra { // We keep references to a few menu actions so we can // enable/disable them at runtime. Glib::RefPtr action_copy, action_undo, action_redo, - action_paste, action_fontsize, action_highlight, + action_paste, action_view_close, action_fontsize, action_highlight, action_stop, action_register, action_console, action_microtex; // Transition animations.