summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/haiku_io.c2
-rw-r--r--src/haiku_select.cc54
-rw-r--r--src/haiku_support.cc5
-rw-r--r--src/haiku_support.h6
-rw-r--r--src/haikuselect.c51
-rw-r--r--src/haikuselect.h5
-rw-r--r--src/haikuterm.c5
-rw-r--r--src/haikuterm.h2
-rw-r--r--src/keyboard.c56
9 files changed, 181 insertions, 5 deletions
diff --git a/src/haiku_io.c b/src/haiku_io.c
index d3455276855..5cc70f6f71f 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 80c5d294820..edb821e3132 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 7819cef5683..9e38d9556fb 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 6260b35cbc1..d73f15560be 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 fe76e09810c..999a0f5ac29 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>
@@ -1021,6 +1022,47 @@ init_haiku_select (void)
}
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)
{
DEFVAR_BOOL ("haiku-signal-invalid-refs", haiku_signal_invalid_refs,
@@ -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 ac8e0698952..d027834e8b6 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 d7247c99e08..bcb3af0e2c3 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 ea20289b5d1..46a2218e492 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 bed8307b6f2..76dc3732b54 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);