From 38c9475e21cf12d06f95a50e93893c59b160453d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 10 May 2025 14:30:56 +0000 Subject: [PATCH 1/3] Fix a number of problems when 'context-stroke' and 'context-fill' are set on elements. --- .../internal/cairo-render-context.cpp | 22 +++++++-- src/extension/internal/cairo-renderer.cpp | 43 ++++-------------- src/object/sp-shape.cpp | 2 +- src/style-internal.cpp | 11 ++++- src/style-internal.h | 16 ++++++- .../pdfoutput/expected/08-clones-1.png | Bin 9810 -> 8610 bytes 6 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 65e473a2ba..7fb1797773 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1341,11 +1341,14 @@ void CairoRenderContext::_setFillStyle(SPStyle const *const style, Geom::OptRect { g_return_if_fail( !style->fill.set || style->fill.isColor() + || style->fill.isContext() || style->fill.isPaintserver() ); float const alpha = _mergedOpacity(SP_SCALE24_TO_FLOAT(style->fill_opacity.value)); SPPaintServer const *paint_server = style->getFillPaintServer(); - if (paint_server && paint_server->isValid()) { + if (style->fill.isContext()) { + // Do nothing. These are valid values but if not inside a or element do nothing. + } else if (paint_server && paint_server->isValid()) { g_assert(is(SP_STYLE_FILL_SERVER(style)) || is(SP_STYLE_FILL_SERVER(style)) @@ -1368,7 +1371,9 @@ void CairoRenderContext::_setFillStyle(SPStyle const *const style, Geom::OptRect void CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &pbox) { float const alpha = _mergedOpacity(SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)); - if (style->stroke.isColor() || (style->stroke.isPaintserver() && !style->getStrokePaintServer()->isValid())) { + if (style->stroke.isContext()) { + // Do nothing. These are valid values but if not inside a or element do nothing. + } else if (style->stroke.isColor() || (style->stroke.isPaintserver() && !style->getStrokePaintServer()->isValid())) { ink_cairo_set_source_color(_cr, style->stroke.getColor(), alpha); } else { g_assert( style->stroke.isPaintserver() @@ -1524,10 +1529,17 @@ bool CairoRenderContext::renderPathVector(Geom::PathVector const &pathv, return true; } - bool no_fill = style->fill.isNone() || style->fill_opacity.value == 0 || + bool no_fill = + style->fill.isNone() || + style->fill.isContext() || + style->fill_opacity.value == 0 || order == STROKE_ONLY; - bool no_stroke = style->stroke.isNone() || (!style->stroke_extensions.hairline && style->stroke_width.computed < 1e-9) || - style->stroke_opacity.value == 0 || order == FILL_ONLY; + bool no_stroke = + style->stroke.isNone() || + style->stroke.isContext() || + (!style->stroke_extensions.hairline && style->stroke_width.computed < 1e-9) || + style->stroke_opacity.value == 0 || + order == FILL_ONLY; if (no_fill && no_stroke) return true; diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 073cd1c981..4bbae3806e 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -179,16 +179,16 @@ public: { auto const fill_origin = target_style->fill.paintOrigin; if (fill_origin == SP_CSS_PAINT_ORIGIN_CONTEXT_FILL) { - _copyPaint(&target_style->fill, _findContextPaint(true)); + _copyPaint(&target_style->fill, *_origin->style->getFillOrStroke(true)); } else if (fill_origin == SP_CSS_PAINT_ORIGIN_CONTEXT_STROKE) { - _copyPaint(&target_style->fill, _findContextPaint(false)); + _copyPaint(&target_style->fill, *_origin->style->getFillOrStroke(false)); } auto const stroke_origin = target_style->stroke.paintOrigin; if (stroke_origin == SP_CSS_PAINT_ORIGIN_CONTEXT_FILL) { - _copyPaint(&target_style->stroke, _findContextPaint(true)); + _copyPaint(&target_style->stroke, *_origin->style->getFillOrStroke(true)); } else if (stroke_origin == SP_CSS_PAINT_ORIGIN_CONTEXT_STROKE) { - _copyPaint(&target_style->stroke, _findContextPaint(false)); + _copyPaint(&target_style->stroke, *_origin->style->getFillOrStroke(false)); } } @@ -204,24 +204,6 @@ public: } private: - /** @brief Find the paint that context-fill or context-stroke is referring to. - * - * @param is_fill If true, handle context-fill, otherwise context-stroke. - * @return The paint relevant to the specified context. - */ - SPIPaint _findContextPaint(bool is_fill) const - { - if (auto *clone = cast(_origin); clone && clone->child) { - // Copy the paint of the child and merge with the parent's. This is similar - // to style merge operations performed when unlinking a clone, but here it's - // done only for a paint. - SPIPaint paint = *clone->child->style->getFillOrStroke(is_fill); - paint.merge(clone->style->getFillOrStroke(is_fill)); - return paint; - } - return *_origin->style->getFillOrStroke(is_fill); - } - /** Copy paint from origin to destination, saving a copy of the old paint. */ template void _copyPaint(PainT *destination, SPIPaint paint) @@ -265,17 +247,7 @@ static void sp_shape_render(SPShape const *shape, CairoRenderContext *ctx, SPIte std::unique_ptr context_fs_manager; if (origin) { - // If the shape is a child of a marker, we must set styles from the origin. - auto parentobj = shape->parent; - while (parentobj) { - if (is(parentobj)) { - // Create a manager to temporarily rewrite any fill/stroke properties - // set to context-fill/context-stroke with usable values. - context_fs_manager = std::make_unique(style, origin); - break; - } - parentobj = parentobj->parent; - } + context_fs_manager = std::make_unique(style, origin); } if (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_NORMAL || @@ -295,12 +267,13 @@ static void sp_shape_render(SPShape const *shape, CairoRenderContext *ctx, SPIte // Render markers bool has_stroke = style->stroke_width.computed > 0.f; - if (shape && shape->hasMarkers() && has_stroke) { + if (shape->hasMarkers() && has_stroke) { for (auto const &[_, marker, tr] : shape->get_markers()) { if (auto marker_item = sp_item_first_item_child(marker)) { auto const old_tr = marker_item->transform; marker_item->transform = old_tr * marker->c2p * tr; - ctx->getRenderer()->renderItem(ctx, marker_item, origin ? origin : shape); + // Marker's context-fill/context-stroke always refer to shape. + ctx->getRenderer()->renderItem(ctx, marker_item, shape); marker_item->transform = old_tr; } } diff --git a/src/object/sp-shape.cpp b/src/object/sp-shape.cpp index 09c9f37878..a166b745ef 100644 --- a/src/object/sp-shape.cpp +++ b/src/object/sp-shape.cpp @@ -686,7 +686,7 @@ void SPShape::update_patheffect(bool write) } Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) { - // std::cout << "SPShape::set_visible(true): " << (getId()?getId():"null") << std::endl; + // std::cout << "SPShape::show(): " << (getId()?getId():"null") << std::endl; Inkscape::DrawingShape *s = new Inkscape::DrawingShape(drawing); bool has_markers = this->hasMarkers(); diff --git a/src/style-internal.cpp b/src/style-internal.cpp index 3af6d08b11..eed7d1a35a 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -1700,6 +1700,7 @@ SPIPaint::read( gchar const *str ) { if (streq(str, "currentColor")) { set = true; paintOrigin = SP_CSS_PAINT_ORIGIN_CURRENT_COLOR; + paintSource = paintOrigin; if (style) { setColor(style->color.getColor()); } else { @@ -1713,9 +1714,11 @@ SPIPaint::read( gchar const *str ) { } else if (streq(str, "context-fill")) { set = true; paintOrigin = SP_CSS_PAINT_ORIGIN_CONTEXT_FILL; + paintSource = paintOrigin; } else if (streq(str, "context-stroke")) { set = true; paintOrigin = SP_CSS_PAINT_ORIGIN_CONTEXT_STROKE; + paintSource = paintOrigin; } else if (streq(str, "none")) { set = true; noneSet = true; @@ -1735,7 +1738,7 @@ const Glib::ustring SPIPaint::get_value() const if (this->href && this->href->getURI()) { ret += this->href->getURI()->cssStr(); } - switch(this->paintOrigin) { + switch(this->paintSource) { case SP_CSS_PAINT_ORIGIN_CURRENT_COLOR: if (!ret.empty()) ret += " "; ret += "currentColor"; @@ -1784,6 +1787,7 @@ SPIPaint::reset( bool init ) { // std::cout << "SPIPaint::reset(): " << name << " " << init << std::endl; SPIBase::clear(); paintOrigin = SP_CSS_PAINT_ORIGIN_NORMAL; + paintSource = paintOrigin; noneSet = false; _color.reset(); tag = nullptr; @@ -1817,6 +1821,8 @@ SPIPaint::cascade( const SPIBase* const parent ) { } else if( p->paintOrigin == SP_CSS_PAINT_ORIGIN_CURRENT_COLOR ) { paintOrigin = SP_CSS_PAINT_ORIGIN_CURRENT_COLOR; _color = style->color.getColor(); + } else if( p->paintOrigin != SP_CSS_PAINT_ORIGIN_NORMAL ) { + paintOrigin = p->paintOrigin; // context fill/stroke } else if( isNone() ) { // } else { @@ -1854,7 +1860,8 @@ SPIPaint::equals(const SPIBase& rhs) const { if ( (this->isColor() != r->isColor() ) || (this->isPaintserver() != r->isPaintserver() ) || - (this->paintOrigin != r->paintOrigin ) ) { + (this->paintOrigin != r->paintOrigin ) || + (this->paintSource != r->paintSource )) { return false; } diff --git a/src/style-internal.h b/src/style-internal.h index ff3972009d..b5c78b29ef 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -737,6 +737,7 @@ public: SPIPaint& operator=(const SPIPaint& rhs) { SPIBase::operator=(rhs); paintOrigin = rhs.paintOrigin; + paintSource = rhs.paintSource; noneSet = rhs.noneSet; _color = rhs._color; href = rhs.href; @@ -746,7 +747,11 @@ public: bool equals(const SPIBase& rhs) const override; bool isSameType( SPIPaint const & other ) const { - return (isPaintserver() == other.isPaintserver()) && (isColor() == other.isColor()) && (paintOrigin == other.paintOrigin); + return + (isPaintserver() == other.isPaintserver()) && + (isColor() == other.isColor()) && + (paintOrigin == other.paintOrigin) && + (paintSource == other.paintSource); } bool isNoneSet() const { @@ -765,6 +770,12 @@ public: return href && href->getObject() != nullptr; } + bool isContext() const { + return + paintOrigin == SP_CSS_PAINT_ORIGIN_CONTEXT_FILL || + paintOrigin == SP_CSS_PAINT_ORIGIN_CONTEXT_STROKE; + } + void setNone() { noneSet = true; _color.reset(); @@ -780,7 +791,8 @@ public: Colors::DocumentCMS const &getCMS() const; // To do: make private public: - SPPaintOrigin paintOrigin : 2; + SPPaintOrigin paintOrigin : 2; // Inherited value (from cascade) + SPPaintOrigin paintSource: 2; // Set value (from XML) bool noneSet : 1; std::shared_ptr href; SPObject *tag = nullptr; diff --git a/testfiles/cli_tests/testcases/pdfoutput/expected/08-clones-1.png b/testfiles/cli_tests/testcases/pdfoutput/expected/08-clones-1.png index c930900518082118cba2fc8e0eb5f45c7498077c..68f63ff911298e09aefad1f931a76f2a40e02370 100644 GIT binary patch literal 8610 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 -- GitLab From d600ec846c711b3a658fe7eba4f071195a0a040d Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 1 Apr 2025 08:27:41 +0200 Subject: [PATCH 2/3] changes ctrl , alt to command , option, refactoring --- share/keys/inkscape.xml | 14 ++++++-------- src/ui/modifiers.cpp | 22 ++++++++++++++++++---- src/ui/tools/arc-tool.cpp | 4 +++- src/ui/tools/gradient-tool.cpp | 9 ++++++--- src/ui/tools/mesh-tool.cpp | 9 ++++++--- src/ui/tools/rect-tool.cpp | 7 +++++-- src/ui/tools/tool-base.cpp | 27 ++++++++++++++++++--------- src/ui/tools/tool-base.h | 2 +- src/ui/util.cpp | 8 ++++++++ src/ui/util.h | 1 + src/ui/widget/events/canvas-event.h | 8 ++++++++ 11 files changed, 80 insertions(+), 31 deletions(-) diff --git a/share/keys/inkscape.xml b/share/keys/inkscape.xml index a2f63dc43e..065a376b26 100644 --- a/share/keys/inkscape.xml +++ b/share/keys/inkscape.xml @@ -29,22 +29,20 @@ override) the bindings in the main default.xml. - - + + - + - + - + - - - + diff --git a/src/ui/modifiers.cpp b/src/ui/modifiers.cpp index c958b10854..53b9082467 100644 --- a/src/ui/modifiers.cpp +++ b/src/ui/modifiers.cpp @@ -254,8 +254,12 @@ std::string generate_label(KeyMask mask, std::string sep) ret.append(_("Hyper")); } if(mask & META) { + #ifdef __APPLE__ + ret.append(_("Command")); + #else if(!ret.empty()) ret.append(sep); ret.append(_("Meta")); + #endif } return ret; } @@ -285,10 +289,15 @@ unsigned long calculate_weight(KeyMask mask) */ void responsive_tooltip(MessageContext *message_context, KeyEvent const &event, int num_args, ...) { + #ifdef __APPLE__ + std::string alt_msg = "Option: "; + #else + std::string alt_msg = "Alt: "; + #endif + std::string meta_msg = "Command: "; std::string ctrl_msg = "Ctrl: "; std::string shift_msg = "Shift: "; - std::string alt_msg = "Alt: "; - + bool meta_case = false; // NOTE: This will hide any keys changed to SUPER or multiple keys such as CTRL+SHIFT va_list args; va_start(args, num_args); @@ -296,6 +305,10 @@ void responsive_tooltip(MessageContext *message_context, KeyEvent const &event, auto modifier = Modifier::get(va_arg(args, Type)); auto name = std::string(_(modifier->get_name())); switch (modifier->get_and_mask()) { + case META: + meta_msg += name + ", "; + meta_case = true; + break; case CTRL: ctrl_msg += name + ", "; break; @@ -313,9 +326,10 @@ void responsive_tooltip(MessageContext *message_context, KeyEvent const &event, ctrl_msg.erase(ctrl_msg.size() - 2); shift_msg.erase(shift_msg.size() - 2); alt_msg.erase(alt_msg.size() - 2); - + if(meta_case) + meta_msg.erase(meta_msg.size() - 2); UI::Tools::sp_event_show_modifier_tip(message_context, event, - ctrl_msg.c_str(), shift_msg.c_str(), alt_msg.c_str()); + ctrl_msg.c_str(), shift_msg.c_str(), alt_msg.c_str(),(meta_case? meta_msg.c_str():nullptr)); } /** diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp index 8f221914cb..7e8e2e74fd 100644 --- a/src/ui/tools/arc-tool.cpp +++ b/src/ui/tools/arc-tool.cpp @@ -42,6 +42,7 @@ #include "ui/widget/events/canvas-event.h" #include "util/units.h" +#include "src/ui/util.h" using Inkscape::DocumentUndo; @@ -383,7 +384,8 @@ void ArcTool::drag(Geom::Point const &pt, unsigned state) } } } else { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Ellipse: %s × %s; with Ctrl to make circle, integer-ratio, or golden-ratio ellipse; with Shift to draw around the starting point"), xs.c_str(), ys.c_str()); + std::string ctrl_command=get_ctrl_or_command(); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Ellipse: %s × %s; with %s to make circle, integer-ratio, or golden-ratio ellipse; with Shift to draw around the starting point"), xs.c_str(), ys.c_str(),ctrl_command.c_str()); } } diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp index cbcdf8e397..c2ce265029 100644 --- a/src/ui/tools/gradient-tool.cpp +++ b/src/ui/tools/gradient-tool.cpp @@ -36,6 +36,8 @@ #include "ui/icon-names.h" #include "ui/tools/gradient-tool.h" #include "ui/widget/events/canvas-event.h" +#include "src/ui/util.h" + using Inkscape::DocumentUndo; @@ -764,10 +766,11 @@ void GradientTool::drag(Geom::Point const &pt, uint32_t etime) // status text; we do not track coords because this branch is run once, not all the time // during drag int const n_objects = boost::distance(selection->items()); + std::string ctrl_command=get_ctrl_or_command(); message_context->setF(NORMAL_MESSAGE, - ngettext("Gradient for %d object; with Ctrl to snap angle", - "Gradient for %d objects; with Ctrl to snap angle", n_objects), - n_objects); + ngettext("Gradient for %d object; with %s to snap angle", + "Gradient for %d objects; with %s to snap angle", n_objects), + n_objects,ctrl_command.c_str()); } else { _desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select objects on which to create gradient.")); } diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 3162c33b2d..0a29e2c173 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -47,6 +47,8 @@ #include "ui/icon-names.h" #include "ui/widget/events/canvas-event.h" +#include "src/ui/util.h" + using Inkscape::DocumentUndo; namespace Inkscape { @@ -887,10 +889,11 @@ void MeshTool::new_default() // status text; we do not track coords because this branch is run once, not all the time // during drag int n_objects = (int) boost::distance(selection->items()); + std::string ctrl_command= get_ctrl_or_command(); message_context->setF(Inkscape::NORMAL_MESSAGE, - ngettext("Gradient for %d object; with Ctrl to snap angle", - "Gradient for %d objects; with Ctrl to snap angle", n_objects), - n_objects); + ngettext("Gradient for %d object; with %s to snap angle", + "Gradient for %d objects; with %s to snap angle", n_objects), + n_objects,ctrl_command.c_str()); } else { _desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select objects on which to create gradient.")); } diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp index 12916edfce..b61b5d0913 100644 --- a/src/ui/tools/rect-tool.cpp +++ b/src/ui/tools/rect-tool.cpp @@ -39,6 +39,8 @@ #include "ui/widget/events/canvas-event.h" #include "util/units.h" +#include "src/ui/util.h" + using Inkscape::DocumentUndo; @@ -379,9 +381,10 @@ void RectTool::drag(Geom::Point const pt, unsigned state) { } } } else { + std::string ctrl_command=get_ctrl_or_command(); this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, - _("Rectangle: %s × %s; with Ctrl to make square, integer-ratio, or golden-ratio rectangle; with Shift to draw around the starting point"), - xs.c_str(), ys.c_str()); + _("Rectangle: %s × %s; with %s to make square, integer-ratio, or golden-ratio rectangle; with Shift to draw around the starting point"), + xs.c_str(), ys.c_str(),ctrl_command.c_str()); } } diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index 7c927aaba7..cbf0c8f63f 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -1262,20 +1262,29 @@ void ToolBase::menu_popup(CanvasEvent const &event, SPObject *obj) */ void sp_event_show_modifier_tip(MessageContext *message_context, KeyEvent const &event, char const *ctrl_tip, char const *shift_tip, - char const *alt_tip) + char const *alt_tip,char const *meta_tip) { auto const keyval = get_latin_keyval(event); - - bool ctrl = ctrl_tip && (mod_ctrl(event) || keyval == GDK_KEY_Control_L || keyval == GDK_KEY_Control_R); - bool shift = shift_tip && (mod_shift(event) || keyval == GDK_KEY_Shift_L || keyval == GDK_KEY_Shift_R); - bool alt = alt_tip && (mod_alt(event) || keyval == GDK_KEY_Alt_L || keyval == GDK_KEY_Alt_R - || keyval == GDK_KEY_Meta_L || keyval == GDK_KEY_Meta_R); - - char *tip = g_strdup_printf("%s%s%s%s%s", ctrl ? ctrl_tip : "", + bool meta = false; + bool ctrl = ctrl_tip && (mod_ctrl(event) || keyval == GDK_KEY_Control_L || keyval == GDK_KEY_Control_R); + bool shift = shift_tip && (mod_shift(event) || keyval == GDK_KEY_Shift_L || keyval == GDK_KEY_Shift_R); + bool alt = alt_tip && (mod_alt(event) || keyval == GDK_KEY_Alt_L || keyval == GDK_KEY_Alt_R); + if(meta_tip){ + meta = meta_tip && (mod_meta(event) || keyval == GDK_KEY_Meta_L || keyval == GDK_KEY_Meta_R); + } + else{ + alt = alt || keyval == GDK_KEY_Meta_L || keyval == GDK_KEY_Meta_R; + } + + char *tip = g_strdup_printf("%s%s%s%s%s%s%s%s", ctrl ? ctrl_tip : "", ctrl && (shift || alt) ? "; " : "", shift ? shift_tip : "", (ctrl || shift) && alt ? "; " : "", - alt ? alt_tip : ""); + alt ? alt_tip : "", + meta ? meta_tip: "", + meta && (shift || alt) ? "; " : "", + (meta || shift) && alt ? "; " : "" + ); if (std::strlen(tip) > 0) { message_context->flash(INFORMATION_MESSAGE, tip); diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h index b79c414a6d..04b6596fbe 100644 --- a/src/ui/tools/tool-base.h +++ b/src/ui/tools/tool-base.h @@ -244,7 +244,7 @@ inline int gobble_key_events(unsigned keyval, unsigned mask) { return 0; } inline void gobble_motion_events(unsigned mask) {} void sp_event_show_modifier_tip(MessageContext *message_context, KeyEvent const &event, - char const *ctrl_tip, char const *shift_tip, char const *alt_tip); + char const *ctrl_tip, char const *shift_tip, char const *alt_tip,char const *meta_tip = nullptr); void init_latin_keys_group(); // Prefer one of the non-_impl versions below. This is public for shortcuts.cpp. diff --git a/src/ui/util.cpp b/src/ui/util.cpp index ce71ebc2c5..13306b04e5 100644 --- a/src/ui/util.cpp +++ b/src/ui/util.cpp @@ -550,6 +550,14 @@ char const *get_text(Gtk::Editable const &editable) return gtk_editable_get_text(const_cast(editable.gobj())); // C API is const-incorrect } +char const* get_ctrl_or_command() +{ + #ifdef __APPLE__ + return "Command"; + #else + return "Ctrl"; + #endif +} /* Local Variables: mode:c++ diff --git a/src/ui/util.h b/src/ui/util.h index 3f21e96d17..0a3796f70f 100644 --- a/src/ui/util.h +++ b/src/ui/util.h @@ -246,6 +246,7 @@ void restrict_minsize_to_square(Gtk::Widget& widget, int min_size_px); /// Get the text from a GtkEditable without the temporary copy imposed by gtkmm. char const *get_text(Gtk::Editable const &editable); +char const* get_ctrl_or_command(); #endif // UI_UTIL_SEEN diff --git a/src/ui/widget/events/canvas-event.h b/src/ui/widget/events/canvas-event.h index a53a0c11eb..fd5bcde7a1 100644 --- a/src/ui/widget/events/canvas-event.h +++ b/src/ui/widget/events/canvas-event.h @@ -332,16 +332,20 @@ inline constexpr auto INK_GDK_MODIFIER_MASK = GDK_SHIFT_MASK | GDK_CONTROL_MASK inline bool mod_shift(unsigned modifiers) { return modifiers & GDK_SHIFT_MASK; } inline bool mod_ctrl(unsigned modifiers) { return modifiers & GDK_CONTROL_MASK; } +inline bool mod_meta(unsigned modifiers) { return modifiers & GDK_META_MASK; } inline bool mod_alt(unsigned modifiers) { return modifiers & GDK_ALT_MASK; } inline bool mod_shift_only(unsigned modifiers) { return (modifiers & INK_GDK_MODIFIER_MASK) == GDK_SHIFT_MASK; } inline bool mod_ctrl_only(unsigned modifiers) { return (modifiers & INK_GDK_MODIFIER_MASK) == GDK_CONTROL_MASK; } +inline bool mod_meta_only(unsigned modifiers) { return (modifiers & INK_GDK_MODIFIER_MASK) == GDK_META_MASK; } inline bool mod_alt_only(unsigned modifiers) { return (modifiers & INK_GDK_MODIFIER_MASK) == GDK_ALT_MASK; } inline bool mod_shift(KeyEvent const &event) { return mod_shift(event.modifiers); } inline bool mod_ctrl(KeyEvent const &event) { return mod_ctrl(event.modifiers); } +inline bool mod_meta(KeyEvent const &event) { return mod_meta(event.modifiers); } inline bool mod_alt(KeyEvent const &event) { return mod_alt(event.modifiers); } inline bool mod_shift_only(KeyEvent const &event) { return mod_shift_only(event.modifiers); } inline bool mod_ctrl_only(KeyEvent const &event) { return mod_ctrl_only(event.modifiers); } +inline bool mod_meta_only(KeyEvent const &event) { return mod_meta_only(event.modifiers); } inline bool mod_alt_only(KeyEvent const &event) { return mod_alt_only(event.modifiers); } /* @@ -351,9 +355,11 @@ inline bool mod_alt_only(KeyEvent const &event) { return mod_alt_only(event.modi inline bool state_held_shift(unsigned state) { return state & GDK_SHIFT_MASK; } inline bool state_held_ctrl(unsigned state) { return state & GDK_CONTROL_MASK; } +inline bool state_held_meta(unsigned state) { return state & GDK_META_MASK; } inline bool state_held_alt(unsigned state) { return state & GDK_ALT_MASK; } inline bool state_held_only_shift(unsigned state) { return (state & INK_GDK_MODIFIER_MASK) == GDK_SHIFT_MASK; } inline bool state_held_only_ctrl(unsigned state) { return (state & INK_GDK_MODIFIER_MASK) == GDK_CONTROL_MASK; } +inline bool state_held_only_meta(unsigned state) { return (state & INK_GDK_MODIFIER_MASK) == GDK_META_MASK; } inline bool state_held_only_alt(unsigned state) { return (state & INK_GDK_MODIFIER_MASK) == GDK_ALT_MASK; } inline bool state_held_any_modifiers(unsigned state) { return state & INK_GDK_MODIFIER_MASK; } inline bool state_held_no_modifiers(unsigned state) { return !state_held_any_modifiers(state); } @@ -363,9 +369,11 @@ inline bool state_held_button(unsigned state) { return (1 <= button || button <= inline bool held_shift(CanvasEvent const &event) { return state_held_shift(event.modifiers); } inline bool held_ctrl(CanvasEvent const &event) { return state_held_ctrl(event.modifiers); } +inline bool held_meta(CanvasEvent const &event) { return state_held_meta(event.modifiers); } inline bool held_alt(CanvasEvent const &event) { return state_held_alt(event.modifiers); } inline bool held_only_shift(CanvasEvent const &event) { return state_held_only_shift(event.modifiers); } inline bool held_only_ctrl(CanvasEvent const &event) { return state_held_only_ctrl(event.modifiers); } +inline bool held_only_meta(CanvasEvent const &event) { return state_held_only_meta(event.modifiers); } inline bool held_only_alt(CanvasEvent const &event) { return state_held_only_alt(event.modifiers); } inline bool held_any_modifiers(CanvasEvent const &event) { return state_held_any_modifiers(event.modifiers); } inline bool held_no_modifiers(CanvasEvent const &event) { return state_held_no_modifiers(event.modifiers); } -- GitLab From 13c5d0938b9dfdc68ef2a3cf903d8b7086f3dfb8 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 11 May 2025 11:00:26 +0300 Subject: [PATCH 3/3] Squashed: changes ctrl_alt to command_option, refactoring, fixed inkscape.xml --- share/keys/inkscape.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/share/keys/inkscape.xml b/share/keys/inkscape.xml index 065a376b26..7e0e3b4a3f 100644 --- a/share/keys/inkscape.xml +++ b/share/keys/inkscape.xml @@ -36,12 +36,14 @@ override) the bindings in the main default.xml. - + + + -- GitLab