emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fd016ea997: Port `x-lost-selection-functions' to Haiku


From: Po Lu
Subject: master fd016ea997: Port `x-lost-selection-functions' to Haiku
Date: Wed, 6 Jul 2022 22:48:47 -0400 (EDT)

branch: master
commit fd016ea99724f7abedfddbb470ab96ece6ddf4ae
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Port `x-lost-selection-functions' to Haiku
    
    * src/haiku_io.c (haiku_len): Add `CLIPBOARD_CHANGED_EVENT'.
    * src/haiku_select.cc (be_update_clipboard_count): Set ownership
    flags.
    (be_handle_clipboard_changed_message):
    (be_start_watching_selection): New functions.
    
    * src/haiku_support.cc (class Emacs): Handle
    B_CLIPBOARD_CHANGED.
    
    * src/haiku_support.h (enum haiku_event_type): New event
    `CLIPBOARD_CHANGED_EVENT'.
    (struct haiku_clipboard_changed_event): New struct.
    
    * src/haikuselect.c (haiku_handle_selection_clear)
    (haiku_selection_disowned, haiku_start_watching_selections): New
    functions.
    (syms_of_haikuselect): New defsym and defvar.
    
    * src/haikuselect.h: Update prototypes.
    * src/haikuterm.c (haiku_read_socket): Handle selection events.
    (haiku_term_init): Start watching selections.
    * src/haikuterm.h: Update prototypes.
    * src/keyboard.c (kbd_buffer_get_event, process_special_events)
    (mark_kboards): Handle SELECTON_CLEAR_EVENTs correctly on Haiku.
---
 src/haiku_io.c       |  2 ++
 src/haiku_select.cc  | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/haiku_support.cc |  5 +++++
 src/haiku_support.h  |  6 ++++++
 src/haikuselect.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 src/haikuselect.h    |  5 +++++
 src/haikuterm.c      |  5 +++++
 src/haikuterm.h      |  2 ++
 src/keyboard.c       | 56 +++++++++++++++++++++++++++++++++++++++++++++++-----
 9 files changed, 181 insertions(+), 5 deletions(-)

diff --git a/src/haiku_io.c b/src/haiku_io.c
index d345527685..5cc70f6f71 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -107,6 +107,8 @@ haiku_len (enum haiku_event_type type)
       return sizeof (struct haiku_scroll_bar_part_event);
     case SCREEN_CHANGED_EVENT:
       return sizeof (struct haiku_screen_changed_event);
+    case CLIPBOARD_CHANGED_EVENT:
+      return sizeof (struct haiku_clipboard_changed_event);
     }
 
   emacs_abort ();
diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 80c5d29482..edb821e313 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -18,6 +18,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
+#include <Application.h>
 #include <Clipboard.h>
 #include <Message.h>
 #include <Path.h>
@@ -47,6 +48,16 @@ static int64 count_primary = -1;
 /* The number of times the secondary selection has changed.  */
 static int64 count_secondary = -1;
 
+/* Whether or not we currently think Emacs owns the primary
+   selection.  */
+static bool owned_primary;
+
+/* Likewise for the secondary selection.  */
+static bool owned_secondary;
+
+/* And the clipboard.  */
+static bool owned_clipboard;
+
 static BClipboard *
 get_clipboard_object (enum haiku_clipboard clipboard)
 {
@@ -150,14 +161,17 @@ be_update_clipboard_count (enum haiku_clipboard id)
     {
     case CLIPBOARD_CLIPBOARD:
       count_clipboard = system_clipboard->SystemCount ();
+      owned_clipboard = true;
       break;
 
     case CLIPBOARD_PRIMARY:
       count_primary = primary->SystemCount ();
+      owned_primary = true;
       break;
 
     case CLIPBOARD_SECONDARY:
       count_secondary = secondary->SystemCount ();
+      owned_secondary = true;
       break;
     }
 }
@@ -433,3 +447,43 @@ be_unlock_clipboard (enum haiku_clipboard clipboard, bool 
discard)
 
   board->Unlock ();
 }
+
+void
+be_handle_clipboard_changed_message (void)
+{
+  if (count_clipboard != -1
+      && (system_clipboard->SystemCount ()
+         > count_clipboard + 1)
+      && owned_clipboard)
+    {
+      owned_clipboard = false;
+      haiku_selection_disowned (CLIPBOARD_CLIPBOARD);
+    }
+
+  if (count_primary != -1
+      && (primary->SystemCount ()
+         > count_primary + 1)
+      && owned_primary)
+    {
+      owned_primary = false;
+      haiku_selection_disowned (CLIPBOARD_PRIMARY);
+    }
+
+  if (count_secondary != -1
+      && (secondary->SystemCount ()
+         > count_secondary + 1)
+      && owned_secondary)
+    {
+      owned_secondary = false;
+      haiku_selection_disowned (CLIPBOARD_SECONDARY);
+    }
+}
+
+void
+be_start_watching_selection (enum haiku_clipboard id)
+{
+  BClipboard *clipboard;
+
+  clipboard = get_clipboard_object (id);
+  clipboard->StartWatching (be_app);
+}
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 7819cef568..9e38d9556f 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -21,6 +21,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <app/Application.h>
 #include <app/Cursor.h>
+#include <app/Clipboard.h>
 #include <app/Messenger.h>
 #include <app/Roster.h>
 
@@ -648,8 +649,12 @@ public:
   void
   MessageReceived (BMessage *msg)
   {
+    struct haiku_clipboard_changed_event rq;
+
     if (msg->what == QUIT_APPLICATION)
       Quit ();
+    else if (msg->what == B_CLIPBOARD_CHANGED)
+      haiku_write (CLIPBOARD_CHANGED_EVENT, &rq);
     else
       BApplication::MessageReceived (msg);
   }
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 6260b35cbc..d73f15560b 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -114,8 +114,14 @@ enum haiku_event_type
     DUMMY_EVENT,
     SCREEN_CHANGED_EVENT,
     MENU_BAR_LEFT,
+    CLIPBOARD_CHANGED_EVENT,
   };
 
+struct haiku_clipboard_changed_event
+{
+  char dummy;
+};
+
 struct haiku_screen_changed_event
 {
   bigtime_t when;
diff --git a/src/haikuselect.c b/src/haikuselect.c
index fe76e09810..999a0f5ac2 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -24,6 +24,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "haikuselect.h"
 #include "haikuterm.h"
 #include "haiku_support.h"
+#include "keyboard.h"
 
 #include <stdlib.h>
 
@@ -1020,6 +1021,47 @@ init_haiku_select (void)
   be_clipboard_init ();
 }
 
+void
+haiku_handle_selection_clear (struct input_event *ie)
+{
+  CALLN (Frun_hook_with_args,
+        Qhaiku_lost_selection_functions, ie->arg);
+}
+
+void
+haiku_selection_disowned (enum haiku_clipboard id)
+{
+  struct input_event ie;
+
+  EVENT_INIT (ie);
+  ie.kind = SELECTION_CLEAR_EVENT;
+
+  switch (id)
+    {
+    case CLIPBOARD_CLIPBOARD:
+      ie.arg = QCLIPBOARD;
+      break;
+
+    case CLIPBOARD_PRIMARY:
+      ie.arg = QPRIMARY;
+      break;
+
+    case CLIPBOARD_SECONDARY:
+      ie.arg = QSECONDARY;
+      break;
+    }
+
+  kbd_buffer_store_event (&ie);
+}
+
+void
+haiku_start_watching_selections (void)
+{
+  be_start_watching_selection (CLIPBOARD_CLIPBOARD);
+  be_start_watching_selection (CLIPBOARD_PRIMARY);
+  be_start_watching_selection (CLIPBOARD_SECONDARY);
+}
+
 void
 syms_of_haikuselect (void)
 {
@@ -1035,12 +1077,21 @@ The function is called without any arguments.  
`mouse-position' can be
 used to retrieve the current position of the mouse.  */);
   Vhaiku_drag_track_function = Qnil;
 
+  DEFVAR_LISP ("haiku-lost-selection-functions", 
Vhaiku_lost_selection_functions,
+    doc: /* A list of functions to be called when Emacs loses an X selection.
+These are only called if a connection to the Haiku display was opened.  */);
+  Vhaiku_lost_selection_functions = Qnil;
+
   DEFSYM (QSECONDARY, "SECONDARY");
   DEFSYM (QCLIPBOARD, "CLIPBOARD");
   DEFSYM (QSTRING, "STRING");
   DEFSYM (QUTF8_STRING, "UTF8_STRING");
   DEFSYM (Qforeign_selection, "foreign-selection");
   DEFSYM (QTARGETS, "TARGETS");
+
+  DEFSYM (Qhaiku_lost_selection_functions,
+         "haiku-lost-selection-functions");
+
   DEFSYM (Qmessage, "message");
   DEFSYM (Qstring, "string");
   DEFSYM (Qref, "ref");
diff --git a/src/haikuselect.h b/src/haikuselect.h
index ac8e069895..d027834e8b 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -38,7 +38,10 @@ enum haiku_clipboard
 extern "C"
 {
 #endif
+/* Defined in haikuselect.c.  */
+extern void haiku_selection_disowned (enum haiku_clipboard);
 
+/* Defined in haiku_select.cc.  */
 extern void be_clipboard_init (void);
 extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, 
ssize_t *);
 extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const 
char *,
@@ -61,6 +64,8 @@ extern int be_add_point_data (void *, const char *, float, 
float);
 extern int be_add_message_message (void *, const char *, void *);
 extern int be_lock_clipboard_message (enum haiku_clipboard, void **, bool);
 extern void be_unlock_clipboard (enum haiku_clipboard, bool);
+extern void be_handle_clipboard_changed_message (void);
+extern void be_start_watching_selection (enum haiku_clipboard);
 
 #ifdef __cplusplus
 };
diff --git a/src/haikuterm.c b/src/haikuterm.c
index d7247c99e0..bcb3af0e2c 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -32,6 +32,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "haiku_support.h"
 #include "thread.h"
 #include "window.h"
+#include "haikuselect.h"
 
 #include <math.h>
 #include <stdlib.h>
@@ -4010,6 +4011,9 @@ haiku_read_socket (struct terminal *terminal, struct 
input_event *hold_quit)
            inev.timestamp = b->when / 1000;
            break;
          }
+       case CLIPBOARD_CHANGED_EVENT:
+         be_handle_clipboard_changed_message ();
+         break;
        case APP_QUIT_REQUESTED_EVENT:
          inev.kind = SAVE_SESSION_EVENT;
          inev.arg = Qt;
@@ -4403,6 +4407,7 @@ haiku_term_init (void)
   else
     dpyinfo->default_name = build_string ("GNU Emacs");
 
+  haiku_start_watching_selections ();
   unblock_input ();
 
   return dpyinfo;
diff --git a/src/haikuterm.h b/src/haikuterm.h
index ea20289b5d..46a2218e49 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -357,4 +357,6 @@ extern void haiku_end_cr_clip (cairo_t *);
 
 extern void haiku_merge_cursor_foreground (struct glyph_string *, unsigned 
long *,
                                           unsigned long *);
+extern void haiku_handle_selection_clear (struct input_event *);
+extern void haiku_start_watching_selections (void);
 #endif /* _HAIKU_TERM_H_ */
diff --git a/src/keyboard.c b/src/keyboard.c
index bed8307b6f..76dc3732b5 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4012,6 +4012,7 @@ kbd_buffer_get_event (KBOARD **kbp,
         We return nil for them.  */
       switch (event->kind)
       {
+#ifndef HAVE_HAIKU
       case SELECTION_REQUEST_EVENT:
       case SELECTION_CLEAR_EVENT:
        {
@@ -4035,6 +4036,20 @@ kbd_buffer_get_event (KBOARD **kbp,
 #endif
        }
         break;
+#else
+      case SELECTION_REQUEST_EVENT:
+       emacs_abort ();
+
+      case SELECTION_CLEAR_EVENT:
+       {
+         struct input_event copy = event->ie;
+
+         kbd_fetch_ptr = next_kbd_event (event);
+         input_pending = readable_events (0);
+         haiku_handle_selection_clear (&copy);
+       }
+       break;
+#endif
 
       case MONITORS_CHANGED_EVENT:
        {
@@ -4345,8 +4360,16 @@ kbd_buffer_get_event (KBOARD **kbp,
 static void
 process_special_events (void)
 {
-  for (union buffered_input_event *event = kbd_fetch_ptr;
-       event != kbd_store_ptr; event = next_kbd_event (event))
+  union buffered_input_event *event;
+#ifndef HAVE_HAIKU
+  struct selection_input_event copy;
+#else
+  struct input_event copy;
+#endif
+  int moved_events;
+
+  for (event = kbd_fetch_ptr;  event != kbd_store_ptr;
+       event = next_kbd_event (event))
     {
       /* If we find a stored X selection request, handle it now.  */
       if (event->kind == SELECTION_REQUEST_EVENT
@@ -4360,8 +4383,7 @@ process_special_events (void)
             between kbd_fetch_ptr and EVENT one slot to the right,
             cyclically.  */
 
-         struct selection_input_event copy = event->sie;
-         int moved_events;
+         copy = event->sie;
 
          if (event < kbd_fetch_ptr)
            {
@@ -4383,6 +4405,27 @@ process_special_events (void)
 #else
          pgtk_handle_selection_event (&copy);
 #endif
+#elif defined HAVE_HAIKU
+         if (event->ie.kind != SELECTION_CLEAR_EVENT)
+           emacs_abort ();
+
+         copy = event->ie;
+
+         if (event < kbd_fetch_ptr)
+           {
+             memmove (kbd_buffer + 1, kbd_buffer,
+                      (event - kbd_buffer) * sizeof *kbd_buffer);
+             kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
+             moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
+           }
+         else
+           moved_events = event - kbd_fetch_ptr;
+
+         memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
+                  moved_events * sizeof *kbd_fetch_ptr);
+         kbd_fetch_ptr = next_kbd_event (kbd_fetch_ptr);
+         input_pending = readable_events (0);
+         haiku_handle_selection_clear (&copy);
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
@@ -13149,7 +13192,10 @@ mark_kboards (void)
     {
       /* These two special event types have no Lisp_Objects to mark.  */
       if (event->kind != SELECTION_REQUEST_EVENT
-         && event->kind != SELECTION_CLEAR_EVENT)
+#ifndef HAVE_HAIKU
+         && event->kind != SELECTION_CLEAR_EVENT
+#endif
+         )
        {
          mark_object (event->ie.x);
          mark_object (event->ie.y);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]