]> git.neil.brown.name Git - edlib.git/commitdiff
introduce core-window.c
authorNeilBrown <neil@brown.name>
Wed, 28 Jun 2023 06:56:39 +0000 (16:56 +1000)
committerNeilBrown <neil@brown.name>
Wed, 28 Jun 2023 07:51:41 +0000 (17:51 +1000)
core-window provides a window-core pane which provides core
functionality for all windows.  Some functionality is moved out of
lib-input where it doesn't really belong.

Signed-off-by: NeilBrown <neil@brown.name>
Makefile
core-editor.c
core-window.c [new file with mode: 0644]
internal.h
lib-input.c

index aac16c2f2a762040441a6330223ffdb0599cfeda..8c718cf9f512133d2adaf8a1f2dea84184d56ad3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ test: edlib lib shared test-rexel
 OBJ = O/edlib.o
 LIBOBJ = O/core-mark.o O/core-doc.o O/core-editor.o O/core-attr.o \
        O/core-keymap.o O/core-pane.o O/core-misc.o O/core-log.o \
-       O/core-version.o
+       O/core-version.o O/core-window.o
 SHOBJ = O/doc-text.o O/doc-dir.o O/doc-docs.o \
        O/doc-email.o O/doc-multipart.o O/doc-list.o \
        O/render-hex.o O/render-lines.o \
index 26b516080c3e04f7026b4e9b27a0f8fb589bab45..4b1ca01b11ac9df59b7eb4737ab385691eeb7390 100644 (file)
@@ -232,6 +232,11 @@ DEF_CMD(editor_activate_display)
        ip = strsave(ci->home, ip);
        p = pane_root(ci->focus);
 
+       p2 = call_ret(pane, "attach-window-core", p);
+       if (!p2)
+               return Efail;
+       p = p2;
+
        for (t = strtok_r(ip, " \t\n", &save);
             t;
             t = strtok_r(NULL, " \t\n", &save)) {
@@ -496,6 +501,7 @@ struct pane *editor_new(void)
        if (ed) {
                doc_setup(ed);
                log_setup(ed);
+               window_setup(ed);
        }
        return ed;
 }
diff --git a/core-window.c b/core-window.c
new file mode 100644 (file)
index 0000000..058b36c
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright Neil Brown ©2023 <neil@brown.name>
+ * May be distributed under terms of GPLv2 - see file:COPYING
+ *
+ * Core per-window functionality.
+ *
+ * Provide a pane that is instantiated between the root and any window
+ * stack, to provide common functionality.  These includes:
+ *
+ * - registering and forwarding per-window notifications
+ * - Being an intermediary for per-window selections.
+ *
+ * ==============================================================
+ * Allow any pane to "claim ownership" of "the selection", or to
+ * "commit" the selection.  A pane can also "discard" the selection,
+ * but that only works if the pane owns it.
+ *
+ * This can be used for mouse-based copy/paste and interaction with the
+ * X11 "PRIMARY" clipboard.
+ * When a selection is made in any pane it claims "the selection".
+ * When a mouse-based paste request is made, the receiving pane can ask for
+ * the selection to be "commited", and then access the most recent copy-buffer.
+ * The owner of a selection will, if the selection is still valid, call
+ * copy:save to save the selected content.
+ * When a "paste" request is made where the location is based on the "point"
+ * (current cursor) it is unlikely that a selection in the same pane should be
+ * used - if there is one it is more likely to be intended to receive the paste.
+ * So the target pane can first "discard" the selection, then "commit", then call
+ * "copy:get".  If the selection is in this pane, the "discard" will succeed,
+ * the "commit" will be a no-op, and the top copy buf will be used.
+ * If the selection is in another pane (or another app via X11), the "discard"
+ * will fail (wrong owner), the "commit" will succeed and copy the selection,
+ * and the "copy:get" will get it.
+ *
+ * Operations are "selection:claim", "selection:commit" and "selection:discard".
+ * When the selection is claimed, the old owner gets called (not notified)
+ * "Notify:selection:claimed", and when a commit request is made,
+ * "Notify:selection:commit" is sent.
+ *
+ * A client can declare itself to be a fall-back handler by calling
+ * select:claim with num==1.  Then if any other client discards its selection,
+ * the ownership reverse to the fallback.  The fallback typically provides
+ * access to some selection external to edlib, such as the x11 selections.
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "core.h"
+#include "internal.h"
+
+struct window_data {
+       struct pane     *sel_owner;
+       int             sel_committed;
+       struct pane     *sel_owner_fallback;
+};
+
+DEF_CMD(request_notify)
+{
+       pane_add_notify(ci->focus, ci->home, ksuffix(ci, "window:request:"));
+       return 1;
+}
+
+DEF_CMD(send_notify)
+{
+       /* window:notify:... */
+       return home_pane_notify(ci->home, ksuffix(ci, "window:notify:"),
+                               ci->focus,
+                               ci->num, ci->mark, ci->str,
+                               ci->num2, ci->mark2, ci->str2, ci->comm2);
+}
+
+DEF_CMD(selection_claim)
+{
+       struct window_data *wd = ci->home->data;
+
+       if (wd->sel_owner && wd->sel_owner != ci->focus) {
+               call("Notify:selection:claimed", wd->sel_owner);
+               //pane_drop_notifiers(ci->home, "Notify:Close", wd->sel_owner);
+       }
+       wd->sel_owner = ci->focus;
+       if (ci->num == 1)
+               wd->sel_owner_fallback = ci->focus;
+       wd->sel_committed = 0;
+       pane_add_notify(ci->home, ci->focus, "Notify:Close");
+       return 1;
+}
+
+DEF_CMD(selection_commit)
+{
+       struct window_data *wd = ci->home->data;
+
+       if (wd->sel_owner && !wd->sel_committed) {
+               if (call("Notify:selection:commit", wd->sel_owner) != 2)
+                       wd->sel_committed = 1;
+       }
+       return 1;
+}
+
+DEF_CMD(selection_discard)
+{
+       struct window_data *wd = ci->home->data;
+       struct pane *op, *fp;
+
+       if (!wd->sel_owner)
+               return Efalse;
+       if (wd->sel_owner_fallback == ci->focus)
+               wd->sel_owner_fallback = NULL;
+       /* Don't require exactly same pane for sel_owner,
+        * but ensure they have the same focus.
+        */
+       op = pane_leaf(wd->sel_owner);
+       fp = pane_leaf(ci->focus);
+       if (fp != op)
+               return Efalse;
+
+       wd->sel_owner = wd->sel_owner_fallback;
+       wd->sel_committed = 0;
+       return 1;
+}
+
+DEF_CMD(close_notify)
+{
+       struct window_data *wd = ci->home->data;
+
+       if (wd->sel_owner_fallback == ci->focus)
+               wd->sel_owner_fallback = NULL;
+
+       if (wd->sel_owner == ci->focus)
+               wd->sel_owner = wd->sel_owner_fallback;
+       return 1;
+}
+
+static struct map *window_map;
+DEF_LOOKUP_CMD(window_handle, window_map);
+
+DEF_CMD(window_attach)
+{
+       struct window_data *wd;
+       struct pane *p;
+
+       alloc(wd, pane);
+       p = pane_register(ci->focus, 0, &window_handle.c, wd);
+       if (!p) {
+               unalloc(wd, pane);
+               return Efail;
+       }
+       comm_call(ci->comm2, "cb", p);
+       return 1;
+}
+
+void window_setup(struct pane *ed safe)
+{
+       window_map = key_alloc();
+
+       key_add_prefix(window_map, "window:request:", &request_notify);
+       key_add_prefix(window_map, "window:notify:", &send_notify);
+
+       key_add(window_map, "selection:claim", &selection_claim);
+       key_add(window_map, "selection:commit", &selection_commit);
+       key_add(window_map, "selection:discard", &selection_discard);
+       key_add(window_map, "Notify:Close", &close_notify);
+
+       call_comm("global-set-command", ed, &window_attach, 0, NULL,
+                 "attach-window-core");
+}
index 903f773d0464b2dca6f1df2d4f82b821cd2085ad..a9d3dfd02ea763af121c70c47f866a8c97b5ce0e 100644 (file)
@@ -23,3 +23,4 @@ void editor_delayed_free(struct pane *ed safe, struct pane *p safe);
 void editor_delayed_mark_free(struct mark *m safe);
 void doc_setup(struct pane *ed safe);
 void log_setup(struct pane *ed safe);
+void window_setup(struct pane *ed safe);
index 1ef8525040aa7e907cb0dca5980123deb12bad50..3ccbce3dd0d3c0e21b1806c4a58d81c535b8a1f6 100644 (file)
@@ -6,38 +6,6 @@
  * This module transalates keystrokes and mouse events into commands.
  * This involves tracking the current 'mode' state.
  *
- * ==============================================================
- * This might belong in a separate pane/module but for now also:
- * Allow any pane to "claim ownership" of "the selection", or to
- * "commit" the selection.  A pane can also "discard" the selection,
- * but that only works if the pane owns it.
- *
- * This can be used for mouse-based copy/paste and interaction with the
- * X11 "PRIMARY" clipboard.
- * When a selection is made in any pane it claims "the selection".
- * When a mouse-based paste request is made, the receiving pane can ask for
- * the selection to be "commited", and then access the most recent copy-buffer.
- * The owner of a selection will, if the selection is still valid, call
- * copy:save to save the selected content.
- * When a "paste" request is made where the location is based on the "point"
- * (current cursor) it is unlikely that a selection in the same pane should be
- * used - if there is one it is more likely to be intended to receive the paste.
- * So the target pane can first "discard" the selection, then "commit", then call
- * "copy:get".  If the selection is in this pane, the "discard" will succeed,
- * the "commit" will be a no-op, and the top copy buf will be used.
- * If the selection is in another pane (or another app via X11), the "discard"
- * will fail (wrong owner), the "commit" will succeed and copy the selection,
- * and the "copy:get" will get it.
- *
- * Operations are "selection:claim", "selection:commit" and "selection:discard".
- * When the selection is claimed, the old owner gets called (not notified)
- * "Notify:selection:claimed", and when a commit request is made,
- * "Notify:selection:commit" is sent.
- *
- * A client can declare itself to be a fall-back handler by calling
- * select:claim with num==1.  Then if any other client discards its selection,
- * the ownership reverse to the fallback.  The fallback typically provides
- * access to some selection external to edlib, such as the x11 selections.
  */
 
 #define _GNU_SOURCE /*  for asprintf */
@@ -66,10 +34,6 @@ struct input_mode {
 
        char            *log[LOGSIZE];
        int             head;
-
-       struct pane     *sel_owner;
-       int             sel_committed;
-       struct pane     *sel_owner_fallback;
 };
 
 /* 'head' is 1 more than the last key added. */
@@ -447,21 +411,6 @@ DEF_CMD(mouse_event)
        return Efalse;
 }
 
-DEF_CMD(request_notify)
-{
-       pane_add_notify(ci->focus, ci->home, ksuffix(ci, "window:request:"));
-       return 1;
-}
-
-DEF_CMD(send_notify)
-{
-       /* window:notify:... */
-       return home_pane_notify(ci->home, ksuffix(ci, "window:notify:"),
-                               ci->focus,
-                               ci->num, ci->mark, ci->str,
-                               ci->num2, ci->mark2, ci->str2, ci->comm2);
-}
-
 DEF_CMD(refocus)
 {
        struct input_mode *im = ci->home->data;
@@ -482,66 +431,11 @@ DEF_CMD(close_focus)
                im->source = NULL;
        }
 
-       if (im->sel_owner_fallback == ci->focus)
-               im->sel_owner_fallback = NULL;
-
-       if (im->sel_owner == ci->focus)
-               im->sel_owner = im->sel_owner_fallback;
-
        if (im->grab == ci->focus)
                im->grab = NULL;
        return 1;
 }
 
-DEF_CMD(selection_claim)
-{
-       struct input_mode *im = ci->home->data;
-
-       if (im->sel_owner && im->sel_owner != ci->focus) {
-               call("Notify:selection:claimed", im->sel_owner);
-               //pane_drop_notifiers(ci->home, "Notify:Close", im->sel_owner);
-       }
-       im->sel_owner = ci->focus;
-       if (ci->num == 1)
-               im->sel_owner_fallback = ci->focus;
-       im->sel_committed = 0;
-       pane_add_notify(ci->home, ci->focus, "Notify:Close");
-       return 1;
-}
-
-DEF_CMD(selection_commit)
-{
-       struct input_mode *im = ci->home->data;
-
-       if (im->sel_owner && !im->sel_committed) {
-               if (call("Notify:selection:commit", im->sel_owner) != 2)
-                       im->sel_committed = 1;
-       }
-       return 1;
-}
-
-DEF_CMD(selection_discard)
-{
-       struct input_mode *im = ci->home->data;
-       struct pane *op, *fp;
-
-       if (!im->sel_owner)
-               return Efalse;
-       if (im->sel_owner_fallback == ci->focus)
-               im->sel_owner_fallback = NULL;
-       /* Don't require exactly same pane for sel_owner,
-        * but ensure they have the same focus.
-        */
-       op = pane_leaf(im->sel_owner);
-       fp = pane_leaf(ci->focus);
-       if (fp != op)
-               return Efalse;
-
-       im->sel_owner = im->sel_owner_fallback;
-       im->sel_committed = 0;
-       return 1;
-}
-
 DEF_CMD(input_free)
 {
        struct input_mode *im = ci->home->data;
@@ -570,13 +464,7 @@ static void register_map(void)
        key_add(im_map, "pane:refocus", &refocus);
        key_add(im_map, "Notify:Close", &close_focus);
        key_add(im_map, "input:log", &log_input);
-       key_add_prefix(im_map, "window:request:", &request_notify);
-       key_add_prefix(im_map, "window:notify:", &send_notify);
        key_add(im_map, "Free", &input_free);
-
-       key_add(im_map, "selection:claim", &selection_claim);
-       key_add(im_map, "selection:commit", &selection_commit);
-       key_add(im_map, "selection:discard", &selection_discard);
 }
 
 DEF_LOOKUP_CMD(input_handle, im_map);