Skip to content

Commit b8ff75d

Browse files
Merge pull request #2225 from KLayout/feature/issue-2214
Implemented a solution for issue #2214
2 parents 1fdae94 + dd8cc89 commit b8ff75d

File tree

7 files changed

+81
-48
lines changed

7 files changed

+81
-48
lines changed

src/edt/edt/edtPartialService.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,8 +2315,8 @@ PartialService::mouse_release_event (const db::DPoint &p, unsigned int buttons,
23152315
if (ui ()->mouse_event_viewport ().contains (p)) {
23162316

23172317
lay::Editable::SelectionMode mode = lay::Editable::Replace;
2318-
bool shift = ((m_buttons & lay::ShiftButton) != 0);
2319-
bool ctrl = ((m_buttons & lay::ControlButton) != 0);
2318+
bool shift = ((buttons & lay::ShiftButton) != 0);
2319+
bool ctrl = ((buttons & lay::ControlButton) != 0);
23202320
if (shift && ctrl) {
23212321
mode = lay::Editable::Invert;
23222322
} else if (shift) {

src/laybasic/laybasic/gsiDeclLayAdded.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,15 @@ class ButtonStateNamespace { };
8484
static int const_ShiftButton() { return (int) lay::ShiftButton; }
8585
static int const_ControlButton() { return (int) lay::ControlButton; }
8686
static int const_AltButton() { return (int) lay::AltButton; }
87+
static int const_ModifierMask() { return (int) lay::ModifierMask; }
8788
static int const_LeftButton() { return (int) lay::LeftButton; }
8889
static int const_MidButton() { return (int) lay::MidButton; }
8990
static int const_RightButton() { return (int) lay::RightButton; }
91+
static int const_MouseButtonMask() { return (int) lay::MouseButtonMask; }
9092

9193
Class<gsi::ButtonStateNamespace> decl_ButtonState ("lay", "ButtonState",
94+
method ("ModifierMask", &const_ModifierMask, "@brief A bit mask that selects all keyboard modifiers in the button state mask\nThis constant has been introduced in version 0.30.6.") +
95+
method ("MouseButtonMask", &const_MouseButtonMask, "@brief A bit mask that selects all mouse buttons in the button state mask\nThis constant has been introduced in version 0.30.6.") +
9296
method ("ShiftKey", &const_ShiftButton, "@brief Indicates that the Shift key is pressed\nThis constant is combined with other constants within \\ButtonState") +
9397
method ("ControlKey", &const_ControlButton, "@brief Indicates that the Control key is pressed\nThis constant is combined with other constants within \\ButtonState") +
9498
method ("AltKey", &const_AltButton, "@brief Indicates that the Alt key is pressed\nThis constant is combined with other constants within \\ButtonState") +

src/laybasic/laybasic/gsiDeclLayPlugin.cc

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -125,58 +125,76 @@ static void drag_cancel_impl (lay::EditorServiceBase *p)
125125

126126
Class<lay::EditorServiceBase> decl_PluginBase ("lay", "PluginBase",
127127
gsi::method_ext ("tracking_position", &tracking_position_impl,
128-
"@brief Gets the tracking position (base class implementation)"
128+
"@brief Gets the tracking position (base class implementation)\n"
129+
"See \\Plugin#tracking_position for details."
129130
) +
130131
gsi::method_ext ("has_tracking_position", &has_tracking_position_impl,
131-
"@brief Gets a value indicating whether the plugin provides a tracking position (base class implementation)"
132+
"@brief Gets a value indicating whether the plugin provides a tracking position (base class implementation)\n"
133+
"See \\Plugin#has_tracking_position for details."
132134
) +
133135
gsi::method_ext ("menu_activated", &menu_activated_impl, gsi::arg ("symbol"),
134-
"@brief Gets called when a custom menu item is selected (base class implementation)"
136+
"@brief Gets called when a custom menu item is selected (base class implementation)\n"
137+
"See \\Plugin#menu_activated for details."
135138
) +
136139
gsi::method_ext ("configure", &configure_impl, gsi::arg ("name"), gsi::arg ("value"),
137-
"@brief Sends configuration requests to the plugin (base class implementation)"
140+
"@brief Sends configuration requests to the plugin (base class implementation)\n"
141+
"See \\Plugin#configure for details."
138142
) +
139143
gsi::method_ext ("config_finalize", &config_finalize_impl,
140-
"@brief Sends the post-configuration request to the plugin (base class implementation)"
144+
"@brief Sends the post-configuration request to the plugin (base class implementation)\n"
145+
"See \\Plugin#config_finalize for details."
141146
) +
142147
gsi::method_ext ("key_event", &key_event_impl, gsi::arg ("key"), gsi::arg ("buttons"),
143-
"@brief Handles the key pressed event (base class implementation)"
148+
"@brief Handles the key pressed event (base class implementation)\n"
149+
"See \\Plugin#key_event for details."
144150
) +
145151
gsi::method_ext ("mouse_button_pressed_event", &mouse_press_event_impl, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
146-
"@brief Handles the mouse button pressed event (base class implementation)"
152+
"@brief Handles the mouse button pressed event (base class implementation)\n"
153+
"See \\Plugin#mouse_button_pressed_event for details."
147154
) +
148155
gsi::method_ext ("mouse_click_event", &mouse_click_event_impl, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
149-
"@brief Handles the mouse button click event after the button has been released (base class implementation)"
156+
"@brief Handles the mouse button click event after the button has been released (base class implementation)\n"
157+
"See \\Plugin#mouse_click_event for details."
150158
) +
151159
gsi::method_ext ("mouse_double_click_event", &mouse_double_click_event_impl, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
152-
"@brief Handles the mouse button double-click event (base class implementation)"
160+
"@brief Handles the mouse button double-click event (base class implementation)\n"
161+
"See \\Plugin#mouse_double_click_event for details."
153162
) +
154163
gsi::method_ext ("leave_event", &leave_event_impl, gsi::arg ("prio"),
155-
"@brief Handles the leave event (base class implementation)"
164+
"@brief Handles the leave event (base class implementation)\n"
165+
"See \\Plugin#leave_event for details."
156166
) +
157167
gsi::method_ext ("enter_event", &enter_event_impl, gsi::arg ("prio"),
158-
"@brief Handles the enter event (base class implementation)"
168+
"@brief Handles the enter event (base class implementation)\n"
169+
"See \\Plugin#enter_event for details."
159170
) +
160171
gsi::method_ext ("mouse_moved_event", &mouse_move_event_impl, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
161-
"@brief Handles the mouse move event (base class implementation)"
172+
"@brief Handles the mouse move event (base class implementation)\n"
173+
"See \\Plugin#mouse_moved_event for details."
162174
) +
163175
gsi::method_ext ("mouse_button_released_event", &mouse_release_event_impl, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
164-
"@brief Handles the mouse button release event (base class implementation)"
176+
"@brief Handles the mouse button release event (base class implementation)\n"
177+
"See \\Plugin#mouse_button_released_event for details."
165178
) +
166179
gsi::method_ext ("wheel_event", &wheel_event_impl, gsi::arg ("delta"), gsi::arg ("horizontal"), gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
167-
"@brief Handles the mouse wheel event (base class implementation)"
180+
"@brief Handles the mouse wheel event (base class implementation)\n"
181+
"See \\Plugin#wheel_event for details."
168182
) +
169183
gsi::method_ext ("activated", &activated_impl,
170-
"@brief Gets called when the plugin is activated (base class implementation)"
184+
"@brief Gets called when the plugin is activated (base class implementation)\n"
185+
"See \\Plugin#activated for details."
171186
) +
172187
gsi::method_ext ("deactivated", &deactivated_impl,
173-
"@brief Gets called when the plugin is deactivated and another plugin is activated (base class implementation)"
188+
"@brief Gets called when the plugin is deactivated and another plugin is activated (base class implementation)\n"
189+
"See \\Plugin#deactivated for details."
174190
) +
175191
gsi::method_ext ("drag_cancel", &drag_cancel_impl,
176-
"@brief This method is called when some mouse dragging operation should be cancelled (base class implementation)"
192+
"@brief This method is called when some mouse dragging operation should be cancelled (base class implementation)\n"
193+
"See \\Plugin#drag_cancel for details."
177194
) +
178195
gsi::method_ext ("update", &update_impl,
179-
"@brief Gets called when the view has changed (base class implementation)"
196+
"@brief Gets called when the view has changed (base class implementation)\n"
197+
"See \\Plugin#update for details."
180198
),
181199
"@brief The plugin base class\n"
182200
"\n"
@@ -735,36 +753,44 @@ Class<gsi::PluginImpl> decl_Plugin (decl_PluginBase, "lay", "Plugin",
735753
) +
736754
callback ("mouse_click_event", &gsi::PluginImpl::mouse_click_event_noref, &gsi::PluginImpl::f_mouse_click_event, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
737755
"@brief Handles the mouse button click event (after the button has been released)\n"
738-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse button has been released without moving it.\n"
756+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse button has been released without moving it.\n"
757+
"A mouse click is not defined by duration, but by releasing a button without moving the mouse after the button was pressed. "
758+
"As a consequence, a \\mouse_button_pressed_event is always issued at the beginning, but it is not followed by a \\mouse_button_released_event.\n"
759+
"Instead, the 'mouse_click_event' is issued.\n"
760+
"\n"
761+
"Starting with version 0.30.6, the button mask reflects the keyboard modifiers at the moment the mouse was released. Before, the keyboard modifiers were "
762+
"captured at the moment when the mouse was pressed."
739763
) +
740764
callback ("mouse_double_click_event", &gsi::PluginImpl::mouse_double_click_event_noref, &gsi::PluginImpl::f_mouse_double_click_event, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
741765
"@brief Handles the mouse button double-click event\n"
742-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse button has been double-clicked.\n"
766+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse button has been double-clicked.\n"
743767
) +
744768
callback ("leave_event", &gsi::PluginImpl::leave_event, &gsi::PluginImpl::f_leave_event, gsi::arg ("prio"),
745769
"@brief Handles the leave event (mouse leaves canvas area of view)\n"
746-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse leaves the canvas area.\n"
770+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse leaves the canvas area.\n"
747771
"This method does not have a position nor button flags.\n"
748772
) +
749773
callback ("enter_event", &gsi::PluginImpl::enter_event, &gsi::PluginImpl::f_enter_event, gsi::arg ("prio"),
750774
"@brief Handles the enter event (mouse enters canvas area of view)\n"
751-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse enters the canvas area.\n"
775+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse enters the canvas area.\n"
752776
"This method does not have a position nor button flags.\n"
753777
) +
754778
callback ("mouse_moved_event", &gsi::PluginImpl::mouse_move_event_noref, &gsi::PluginImpl::f_mouse_move_event, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
755779
"@brief Handles the mouse move event\n"
756-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse is moved in the canvas area.\n"
780+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse is moved in the canvas area.\n"
757781
"\n"
758782
"The mouse move event is important for a number of background jobs, such as coordinate display in the status bar.\n"
759783
"Hence, you should not consume the event - i.e. you should return 'false' from this method.\n"
760784
) +
761785
callback ("mouse_button_released_event", &gsi::PluginImpl::mouse_release_event_noref, &gsi::PluginImpl::f_mouse_release_event, gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
762786
"@brief Handles the mouse button release event\n"
763-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse button is released.\n"
787+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse button is released.\n"
788+
"Starting with version 0.30.6, the button mask reflects the keyboard modifiers at the moment the mouse was released. Before, the keyboard modifiers were "
789+
"captured at the moment when the mouse was pressed."
764790
) +
765791
callback ("wheel_event", &gsi::PluginImpl::wheel_event_noref, &gsi::PluginImpl::f_wheel_event, gsi::arg ("delta"), gsi::arg ("horizontal"), gsi::arg ("p"), gsi::arg ("buttons"), gsi::arg ("prio"),
766792
"@brief Handles the mouse wheel event\n"
767-
"The behaviour of this callback is the same than for \\mouse_press_event, except that it is called when the mouse wheel is rotated.\n"
793+
"The behaviour of this callback is the same than for \\mouse_button_pressed_event, except that it is called when the mouse wheel is rotated.\n"
768794
"Additional parameters for this event are 'delta' (the rotation angle in units of 1/8th degree) and 'horizontal' which is true when the horizontal wheel was rotated and "
769795
"false if the vertical wheel was rotated.\n"
770796
) +

src/laybasic/laybasic/laySelector.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ SelectionService::SelectionService (lay::LayoutViewBase *view) :
4747
mp_view (view),
4848
mp_box (0),
4949
m_color (0),
50-
m_buttons (0),
5150
m_hover (false),
5251
m_hover_wait (false),
5352
m_mouse_in_window (false)
@@ -204,7 +203,6 @@ SelectionService::mouse_press_event (const db::DPoint &p, unsigned int buttons,
204203

205204
if ((buttons & lay::LeftButton) != 0) {
206205
mp_view->stop_redraw (); // TODO: how to restart if selection is aborted?
207-
m_buttons = buttons;
208206
begin (p);
209207
return true;
210208
}
@@ -263,7 +261,7 @@ SelectionService::mouse_click_event (const db::DPoint &p, unsigned int buttons,
263261
}
264262

265263
bool
266-
SelectionService::mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool prio)
264+
SelectionService::mouse_release_event (const db::DPoint & /*p*/, unsigned int buttons, bool prio)
267265
{
268266
hover_reset ();
269267

@@ -274,8 +272,8 @@ SelectionService::mouse_release_event (const db::DPoint & /*p*/, unsigned int /*
274272
if (mp_view) {
275273

276274
lay::Editable::SelectionMode mode = lay::Editable::Replace;
277-
bool shift = ((m_buttons & lay::ShiftButton) != 0);
278-
bool ctrl = ((m_buttons & lay::ControlButton) != 0);
275+
bool shift = ((buttons & lay::ShiftButton) != 0);
276+
bool ctrl = ((buttons & lay::ControlButton) != 0);
279277
if (shift && ctrl) {
280278
mode = lay::Editable::Invert;
281279
} else if (shift) {

src/laybasic/laybasic/laySelector.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ public slots:
9191
lay::LayoutViewBase *mp_view;
9292
lay::RubberBox *mp_box;
9393
unsigned int m_color;
94-
unsigned int m_buttons;
9594
bool m_hover;
9695
bool m_hover_wait;
9796
db::DPoint m_hover_point;

src/laybasic/laybasic/layViewObject.cc

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ ViewObjectUI::send_mouse_double_clicked_event (const db::DPoint &pt, unsigned in
907907
}
908908

909909
void
910-
ViewObjectUI::send_mouse_release_event (const db::DPoint &pt, unsigned int /*buttons*/)
910+
ViewObjectUI::send_mouse_release_event (const db::DPoint &pt, unsigned int buttons)
911911
{
912912
try {
913913

@@ -916,23 +916,27 @@ ViewObjectUI::send_mouse_release_event (const db::DPoint &pt, unsigned int /*but
916916

917917
bool done = false;
918918

919+
// Qt does not include the released button in the mask, so we take the mouse buttons that we stored
920+
// on "press", but use the current modifiers (issue #2214)
921+
unsigned int effective_buttons = (m_mouse_buttons & lay::MouseButtonMask) | (buttons & lay::ModifierMask);
922+
919923
m_mouse_pos = pt;
920924
db::DPoint p = pixel_to_um (m_mouse_pos);
921925

922926
auto grabbed = m_grabbed;
923927
for (auto g = grabbed.begin (); !done && g != grabbed.end (); ++g) {
924928
if (m_mouse_pressed_state) {
925-
done = (*g)->enabled () && (*g)->mouse_click_event (p, m_mouse_buttons, true);
929+
done = (*g)->enabled () && (*g)->mouse_click_event (p, effective_buttons, true);
926930
} else {
927-
done = (*g)->enabled () && (*g)->mouse_release_event (p, m_mouse_buttons, true);
931+
done = (*g)->enabled () && (*g)->mouse_release_event (p, effective_buttons, true);
928932
}
929933
}
930934

931935
if (! done && mp_active_service && mp_active_service->enabled ()) {
932936
if (m_mouse_pressed_state) {
933-
done = mp_active_service->mouse_click_event (p, m_mouse_buttons, true);
937+
done = mp_active_service->mouse_click_event (p, effective_buttons, true);
934938
} else {
935-
done = mp_active_service->mouse_release_event (p, m_mouse_buttons, true);
939+
done = mp_active_service->mouse_release_event (p, effective_buttons, true);
936940
}
937941
}
938942

@@ -942,19 +946,19 @@ ViewObjectUI::send_mouse_release_event (const db::DPoint &pt, unsigned int /*but
942946
++next;
943947
if ((*svc)->enabled ()) {
944948
if (m_mouse_pressed_state) {
945-
done = (*svc)->mouse_click_event (p, m_mouse_buttons, false);
949+
done = (*svc)->mouse_click_event (p, effective_buttons, false);
946950
} else {
947-
done = (*svc)->mouse_release_event (p, m_mouse_buttons, false);
951+
done = (*svc)->mouse_release_event (p, effective_buttons, false);
948952
}
949953
}
950954
svc = next;
951955
}
952956

953957
if (! done) {
954958
if (m_mouse_pressed_state) {
955-
mouse_click_event (p, m_mouse_buttons);
959+
mouse_click_event (p, effective_buttons);
956960
} else {
957-
mouse_release_event (p, m_mouse_buttons);
961+
mouse_release_event (p, effective_buttons);
958962
}
959963
}
960964

src/laybasic/laybasic/layViewObject.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -548,12 +548,14 @@ class LAYBASIC_PUBLIC ViewObject
548548
* @brief Describes the button state (supposed to be ored)
549549
*/
550550
enum ButtonState {
551-
ShiftButton = 1,
552-
ControlButton = 2,
553-
AltButton = 4,
554-
LeftButton = 8,
555-
MidButton = 16,
556-
RightButton = 32
551+
ShiftButton = 0x01,
552+
ControlButton = 0x02,
553+
AltButton = 0x04,
554+
ModifierMask = 0x07, // all keyboard modifiers
555+
LeftButton = 0x08,
556+
MidButton = 0x10,
557+
RightButton = 0x20,
558+
MouseButtonMask = 0x38 // all mouse buttons
557559
};
558560

559561
/**

0 commit comments

Comments
 (0)