diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-12 22:27:02 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-12 22:27:02 +0200 |
commit | 9cdf86dc8dda0ebf777dfdec5c1eeef53371a1ee (patch) | |
tree | 340b4bac4c96c9711e4845ff994701176a3dd267 /src | |
parent | 3e56e0f1ca20d7d0489036ce0f0bca97d596f0d5 (diff) |
Cut/copy/paste paste via menus
IssueID #175
Diffstat (limited to 'src')
-rw-r--r-- | src/defs.h | 5 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 28 | ||||
-rw-r--r-- | src/ui/util.c | 15 | ||||
-rw-r--r-- | src/ui/util.h | 1 | ||||
-rw-r--r-- | src/ui/widget.c | 9 | ||||
-rw-r--r-- | src/ui/widget.h | 1 | ||||
-rw-r--r-- | src/ui/window.c | 21 |
7 files changed, 70 insertions, 10 deletions
@@ -74,3 +74,8 @@ enum iFileVersion { | |||
74 | #define rightAngle_Icon "\U0001fba5" | 74 | #define rightAngle_Icon "\U0001fba5" |
75 | #define planet_Icon "\U0001fa90" | 75 | #define planet_Icon "\U0001fa90" |
76 | #define info_Icon "\u2139" | 76 | #define info_Icon "\u2139" |
77 | #define leftHalf_Icon "\u25e7" | ||
78 | #define rightHalf_Icon "\u25e8" | ||
79 | #define scissor_Icon "\u2700" | ||
80 | #define clipCopy_Icon "\u2398" | ||
81 | #define clipboard_Icon "\U0001f4cb" | ||
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index eac195b9..f4302887 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -314,9 +314,13 @@ void selectAll_InputWidget(iInputWidget *d) { | |||
314 | refresh_Widget(as_Widget(d)); | 314 | refresh_Widget(as_Widget(d)); |
315 | } | 315 | } |
316 | 316 | ||
317 | iLocalDef iBool isEditing_InputWidget_(const iInputWidget *d) { | ||
318 | return (flags_Widget(constAs_Widget(d)) & selected_WidgetFlag) != 0; | ||
319 | } | ||
320 | |||
317 | void begin_InputWidget(iInputWidget *d) { | 321 | void begin_InputWidget(iInputWidget *d) { |
318 | iWidget *w = as_Widget(d); | 322 | iWidget *w = as_Widget(d); |
319 | if (flags_Widget(w) & selected_WidgetFlag) { | 323 | if (isEditing_InputWidget_(d)) { |
320 | /* Already active. */ | 324 | /* Already active. */ |
321 | return; | 325 | return; |
322 | } | 326 | } |
@@ -346,7 +350,7 @@ void begin_InputWidget(iInputWidget *d) { | |||
346 | 350 | ||
347 | void end_InputWidget(iInputWidget *d, iBool accept) { | 351 | void end_InputWidget(iInputWidget *d, iBool accept) { |
348 | iWidget *w = as_Widget(d); | 352 | iWidget *w = as_Widget(d); |
349 | if (~flags_Widget(w) & selected_WidgetFlag) { | 353 | if (!isEditing_InputWidget_(d)) { |
350 | /* Was not active. */ | 354 | /* Was not active. */ |
351 | return; | 355 | return; |
352 | } | 356 | } |
@@ -614,6 +618,15 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
614 | end_InputWidget(d, iTrue); | 618 | end_InputWidget(d, iTrue); |
615 | return iFalse; | 619 | return iFalse; |
616 | } | 620 | } |
621 | else if ((isCommand_UserEvent(ev, "copy") || isCommand_UserEvent(ev, "input.copy")) && | ||
622 | isEditing_InputWidget_(d)) { | ||
623 | copy_InputWidget_(d, argLabel_Command(command_UserEvent(ev), "cut")); | ||
624 | return iTrue; | ||
625 | } | ||
626 | else if (isCommand_UserEvent(ev, "input.paste") && isEditing_InputWidget_(d)) { | ||
627 | paste_InputWidget_(d); | ||
628 | return iTrue; | ||
629 | } | ||
617 | else if (isCommand_UserEvent(ev, "theme.changed")) { | 630 | else if (isCommand_UserEvent(ev, "theme.changed")) { |
618 | if (d->buffered) { | 631 | if (d->buffered) { |
619 | updateBuffered_InputWidget_(d); | 632 | updateBuffered_InputWidget_(d); |
@@ -675,6 +688,17 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
675 | case finished_ClickResult: | 688 | case finished_ClickResult: |
676 | return iTrue; | 689 | return iTrue; |
677 | } | 690 | } |
691 | if (ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT && | ||
692 | contains_Widget(w, init_I2(ev->button.x, ev->button.y))) { | ||
693 | iWidget *clipMenu = findWidget_App("clipmenu"); | ||
694 | if (isVisible_Widget(clipMenu)) { | ||
695 | closeMenu_Widget(clipMenu); | ||
696 | } | ||
697 | else { | ||
698 | openMenuFlags_Widget(clipMenu, mouseCoord_Window(get_Window()), iFalse); | ||
699 | } | ||
700 | return iTrue; | ||
701 | } | ||
678 | if (ev->type == SDL_KEYUP && isFocused_Widget(w)) { | 702 | if (ev->type == SDL_KEYUP && isFocused_Widget(w)) { |
679 | return iTrue; | 703 | return iTrue; |
680 | } | 704 | } |
diff --git a/src/ui/util.c b/src/ui/util.c index 04dbe190..adb3c4b4 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -517,14 +517,21 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | |||
517 | } | 517 | } |
518 | 518 | ||
519 | void openMenu_Widget(iWidget *d, iInt2 coord) { | 519 | void openMenu_Widget(iWidget *d, iInt2 coord) { |
520 | openMenuFlags_Widget(d, coord, iTrue); | ||
521 | } | ||
522 | |||
523 | void openMenuFlags_Widget(iWidget *d, iInt2 coord, iBool postCommands) { | ||
520 | const iInt2 rootSize = rootSize_Window(get_Window()); | 524 | const iInt2 rootSize = rootSize_Window(get_Window()); |
521 | const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); | 525 | const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); |
522 | const iBool isSlidePanel = (flags_Widget(d) & horizontalOffset_WidgetFlag) != 0; | 526 | const iBool isSlidePanel = (flags_Widget(d) & horizontalOffset_WidgetFlag) != 0; |
527 | if (postCommands) { | ||
528 | postCommand_App("cancel"); /* dismiss any other menus */ | ||
529 | } | ||
523 | /* Menu closes when commands are emitted, so handle any pending ones beforehand. */ | 530 | /* Menu closes when commands are emitted, so handle any pending ones beforehand. */ |
524 | postCommand_App("cancel"); /* dismiss any other menus */ | ||
525 | processEvents_App(postedEventsOnly_AppEventMode); | 531 | processEvents_App(postedEventsOnly_AppEventMode); |
526 | setFlags_Widget(d, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); | 532 | setFlags_Widget(d, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); |
527 | setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); | 533 | setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); |
534 | raise_Widget(d); | ||
528 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); | 535 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); |
529 | if (isPortraitPhone) { | 536 | if (isPortraitPhone) { |
530 | setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); | 537 | setFlags_Widget(d, arrangeWidth_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, iFalse); |
@@ -576,7 +583,7 @@ void openMenu_Widget(iWidget *d, iInt2 coord) { | |||
576 | float l, t, r, b; | 583 | float l, t, r, b; |
577 | safeAreaInsets_iOS(&l, &t, &r, &b); | 584 | safeAreaInsets_iOS(&l, &t, &r, &b); |
578 | topExcess += t; | 585 | topExcess += t; |
579 | bottomExcess += b; | 586 | bottomExcess += iMax(b, get_Window()->keyboardHeight); |
580 | leftExcess += l; | 587 | leftExcess += l; |
581 | rightExcess += r; | 588 | rightExcess += r; |
582 | } | 589 | } |
@@ -594,7 +601,9 @@ void openMenu_Widget(iWidget *d, iInt2 coord) { | |||
594 | d->rect.pos.x += leftExcess; | 601 | d->rect.pos.x += leftExcess; |
595 | } | 602 | } |
596 | postRefresh_App(); | 603 | postRefresh_App(); |
597 | postCommand_Widget(d, "menu.opened"); | 604 | if (postCommands) { |
605 | postCommand_Widget(d, "menu.opened"); | ||
606 | } | ||
598 | if (isPortraitPhone) { | 607 | if (isPortraitPhone) { |
599 | setVisualOffset_Widget(d, isSlidePanel ? width_Widget(d) : height_Widget(d), 0, 0); | 608 | setVisualOffset_Widget(d, isSlidePanel ? width_Widget(d) : height_Widget(d), 0, 0); |
600 | setVisualOffset_Widget(d, 0, 330, easeOut_AnimFlag | softer_AnimFlag); | 609 | setVisualOffset_Widget(d, 0, 330, easeOut_AnimFlag | softer_AnimFlag); |
diff --git a/src/ui/util.h b/src/ui/util.h index 7a66ebb3..e2461b9d 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -172,6 +172,7 @@ struct Impl_MenuItem { | |||
172 | 172 | ||
173 | iWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */ | 173 | iWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */ |
174 | void openMenu_Widget (iWidget *, iInt2 coord); | 174 | void openMenu_Widget (iWidget *, iInt2 coord); |
175 | void openMenuFlags_Widget(iWidget *d, iInt2 coord, iBool postCommands); | ||
175 | void closeMenu_Widget (iWidget *); | 176 | void closeMenu_Widget (iWidget *); |
176 | 177 | ||
177 | iLabelWidget * findMenuItem_Widget (iWidget *menu, const char *command); | 178 | iLabelWidget * findMenuItem_Widget (iWidget *menu, const char *command); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 4d319808..4fad3c86 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -1207,6 +1207,15 @@ static void printTree_Widget_(const iWidget *d, int indent) { | |||
1207 | } | 1207 | } |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | void raise_Widget(iWidget *d) { | ||
1211 | iPtrArray *onTop = onTop_RootData_(); | ||
1212 | if (d->flags & keepOnTop_WidgetFlag) { | ||
1213 | iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); | ||
1214 | removeOne_PtrArray(onTop, d); | ||
1215 | pushBack_PtrArray(onTop, d); | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1210 | iBool hasVisibleChildOnTop_Widget(const iWidget *parent) { | 1219 | iBool hasVisibleChildOnTop_Widget(const iWidget *parent) { |
1211 | iConstForEach(ObjectList, i, parent->children) { | 1220 | iConstForEach(ObjectList, i, parent->children) { |
1212 | const iWidget *child = i.object; | 1221 | const iWidget *child = i.object; |
diff --git a/src/ui/widget.h b/src/ui/widget.h index 37c8efdc..a00bb3b7 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -243,6 +243,7 @@ iWidget * hover_Widget (void); | |||
243 | void unhover_Widget (void); | 243 | void unhover_Widget (void); |
244 | void setMouseGrab_Widget (iWidget *); | 244 | void setMouseGrab_Widget (iWidget *); |
245 | iWidget * mouseGrab_Widget (void); | 245 | iWidget * mouseGrab_Widget (void); |
246 | void raise_Widget (iWidget *); | ||
246 | iBool hasVisibleChildOnTop_Widget | 247 | iBool hasVisibleChildOnTop_Widget |
247 | (const iWidget *parent); | 248 | (const iWidget *parent); |
248 | void printTree_Widget (const iWidget *); | 249 | void printTree_Widget (const iWidget *); |
diff --git a/src/ui/window.c b/src/ui/window.c index 16f217a3..5b65f173 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -262,7 +262,10 @@ static const iMenuItem fileMenuItems_[] = { | |||
262 | }; | 262 | }; |
263 | 263 | ||
264 | static const iMenuItem editMenuItems_[] = { | 264 | static const iMenuItem editMenuItems_[] = { |
265 | { "Cut", SDLK_x, KMOD_PRIMARY, "input.copy cut:1" }, | ||
265 | { "Copy", SDLK_c, KMOD_PRIMARY, "copy" }, | 266 | { "Copy", SDLK_c, KMOD_PRIMARY, "copy" }, |
267 | { "Paste", SDLK_v, KMOD_PRIMARY, "input.paste" }, | ||
268 | { "---", 0, 0, NULL }, | ||
266 | { "Copy Link to Page", SDLK_c, KMOD_PRIMARY | KMOD_SHIFT, "document.copylink" }, | 269 | { "Copy Link to Page", SDLK_c, KMOD_PRIMARY | KMOD_SHIFT, "document.copylink" }, |
267 | { "---", 0, 0, NULL }, | 270 | { "---", 0, 0, NULL }, |
268 | { "Find", SDLK_f, KMOD_PRIMARY, "focus.set id:find.input" }, | 271 | { "Find", SDLK_f, KMOD_PRIMARY, "focus.set id:find.input" }, |
@@ -581,7 +584,6 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { | |||
581 | iWidget *urlBar = findChild_Widget(navBar, "url"); | 584 | iWidget *urlBar = findChild_Widget(navBar, "url"); |
582 | urlBar->rect.size.x = iMini(navBarAvailableSpace_(navBar), 167 * gap_UI); | 585 | urlBar->rect.size.x = iMini(navBarAvailableSpace_(navBar), 167 * gap_UI); |
583 | arrange_Widget(navBar); | 586 | arrange_Widget(navBar); |
584 | printTree_Widget(urlBar); | ||
585 | } | 587 | } |
586 | refresh_Widget(navBar); | 588 | refresh_Widget(navBar); |
587 | postCommand_Widget(navBar, "layout.changed id:navbar"); | 589 | postCommand_Widget(navBar, "layout.changed id:navbar"); |
@@ -1134,7 +1136,7 @@ static void setupUserInterface_Window(iWindow *d) { | |||
1134 | } | 1136 | } |
1135 | #endif | 1137 | #endif |
1136 | updatePadding_Window_(d); | 1138 | updatePadding_Window_(d); |
1137 | /* Context menus. */ { | 1139 | /* Global context menus. */ { |
1138 | iWidget *tabsMenu = makeMenu_Widget(d->root, | 1140 | iWidget *tabsMenu = makeMenu_Widget(d->root, |
1139 | (iMenuItem[]){ | 1141 | (iMenuItem[]){ |
1140 | { close_Icon " Close Tab", 0, 0, "tabs.close" }, | 1142 | { close_Icon " Close Tab", 0, 0, "tabs.close" }, |
@@ -1145,13 +1147,22 @@ static void setupUserInterface_Window(iWindow *d) { | |||
1145 | { barRightArrow_Icon " Close Tabs To Right", 0, 0, "tabs.close toright:1" }, | 1147 | { barRightArrow_Icon " Close Tabs To Right", 0, 0, "tabs.close toright:1" }, |
1146 | }, | 1148 | }, |
1147 | 6); | 1149 | 6); |
1148 | setId_Widget(tabsMenu, "doctabs.menu"); | ||
1149 | iWidget *barMenu = makeMenu_Widget(d->root, | 1150 | iWidget *barMenu = makeMenu_Widget(d->root, |
1150 | (iMenuItem[]) { | 1151 | (iMenuItem[]) { |
1151 | { "Toggle Left Sidebar", 0, 0, "sidebar.toggle" }, | 1152 | { leftHalf_Icon " Toggle Left Sidebar", 0, 0, "sidebar.toggle" }, |
1152 | { "Toggle Right Sidebar", 0, 0, "sidebar2.toggle" }, | 1153 | { rightHalf_Icon " Toggle Right Sidebar", 0, 0, "sidebar2.toggle" }, |
1153 | }, 2); | 1154 | }, 2); |
1155 | iWidget *clipMenu = makeMenu_Widget(d->root, | ||
1156 | (iMenuItem[]){ | ||
1157 | { scissor_Icon " Cut", 0, 0, "input.copy cut:1" }, | ||
1158 | { clipCopy_Icon " Copy", 0, 0, "input.copy" }, | ||
1159 | { "---", 0, 0, NULL }, | ||
1160 | { clipboard_Icon " Paste", 0, 0, "input.paste" }, | ||
1161 | }, | ||
1162 | 4); | ||
1163 | setId_Widget(tabsMenu, "doctabs.menu"); | ||
1154 | setId_Widget(barMenu, "barmenu"); | 1164 | setId_Widget(barMenu, "barmenu"); |
1165 | setId_Widget(clipMenu, "clipmenu"); | ||
1155 | } | 1166 | } |
1156 | /* Global keyboard shortcuts. */ { | 1167 | /* Global keyboard shortcuts. */ { |
1157 | addAction_Widget(d->root, 'l', KMOD_PRIMARY, "navigate.focus"); | 1168 | addAction_Widget(d->root, 'l', KMOD_PRIMARY, "navigate.focus"); |