diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/haiku_io.c | 2 | ||||
-rw-r--r-- | src/haiku_select.cc | 54 | ||||
-rw-r--r-- | src/haiku_support.cc | 5 | ||||
-rw-r--r-- | src/haiku_support.h | 6 | ||||
-rw-r--r-- | src/haikuselect.c | 51 | ||||
-rw-r--r-- | src/haikuselect.h | 5 | ||||
-rw-r--r-- | src/haikuterm.c | 5 | ||||
-rw-r--r-- | src/haikuterm.h | 2 | ||||
-rw-r--r-- | src/keyboard.c | 56 |
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 (©); + } + 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 (©); #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 (©); #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); |