summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-03-16 13:18:12 +0000
committerPo Lu <luangruo@yahoo.com>2022-03-16 13:28:53 +0000
commit3de3f12b9402c731aca1a583a15fc6245efea136 (patch)
treedd0b83c98156cb6aecd01d40bdda7ef20df05844
parent65f92837fa58c943f689fb847edcfd44c8a8a6c1 (diff)
downloademacs-3de3f12b9402c731aca1a583a15fc6245efea136.tar.gz
Redo Haiku DND support
* lisp/term/haiku-win.el (haiku-dnd-handle-drag-n-drop-event): Update for new DND event format. * src/haiku_io.c (haiku_len): Handle DRAG_AND_DROP_EVENTs. * src/haiku_select.cc (be_enum_message, be_get_refs_data) (be_get_message_data): New function. * src/haiku_support.cc (class Emacs): Remove `RefsReceived'. (MessageReceived): Generate new kind of drag-n-drop events. * src/haiku_support.h (enum haiku_event_type): Rename `REFS_EVENT' to `DRAG_AND_DROP_EVENT'. (struct haiku_refs_event): Delete struct. (struct haiku_drag_and_drop_event): New struct. * src/haikuselect.c (haiku_message_to_lisp): New function. (syms_of_haikuselect): New symbols. * src/haikuselect.h: Update prototypes. * src/haikuterm.c (haiku_read_socket): Handle new type of drag-and-drop events by serializing drop message to Lisp and letting Lisp code do the processing. * src/haikuterm.h: Update prototypes.
-rw-r--r--lisp/term/haiku-win.el11
-rw-r--r--src/haiku_io.c4
-rw-r--r--src/haiku_select.cc64
-rw-r--r--src/haiku_support.cc59
-rw-r--r--src/haiku_support.h10
-rw-r--r--src/haikuselect.c140
-rw-r--r--src/haikuselect.h14
-rw-r--r--src/haikuterm.c12
-rw-r--r--src/haikuterm.h1
9 files changed, 254 insertions, 61 deletions
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index c4810f116d2..322f1a18de6 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -130,9 +130,14 @@ If TYPE is nil, return \"text/plain\"."
(interactive "e")
(let* ((string (caddr event))
(window (posn-window (event-start event))))
- (with-selected-window window
- (raise-frame)
- (dnd-handle-one-url window 'private (concat "file:" string)))))
+ (cond
+ ((assoc "refs" string)
+ (with-selected-window window
+ (raise-frame)
+ (dolist (filename (cddr (assoc "refs" string)))
+ (dnd-handle-one-url window 'private
+ (concat "file:" filename)))))
+ (t (message "Don't know how to drop: %s" event)))))
(define-key special-event-map [drag-n-drop]
'haiku-dnd-handle-drag-n-drop-event)
diff --git a/src/haiku_io.c b/src/haiku_io.c
index f9fa4095f9f..89f0877eb67 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -90,8 +90,8 @@ haiku_len (enum haiku_event_type type)
return sizeof (struct haiku_menu_bar_help_event);
case ZOOM_EVENT:
return sizeof (struct haiku_zoom_event);
- case REFS_EVENT:
- return sizeof (struct haiku_refs_event);
+ case DRAG_AND_DROP_EVENT:
+ return sizeof (struct haiku_drag_and_drop_event);
case APP_QUIT_REQUESTED_EVENT:
return sizeof (struct haiku_app_quit_requested_event);
case DUMMY_EVENT:
diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 011ad58036f..abb07b20028 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -19,6 +19,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <Clipboard.h>
+#include <Message.h>
+#include <Path.h>
+#include <Entry.h>
#include <cstdlib>
#include <cstring>
@@ -257,3 +260,64 @@ init_haiku_select (void)
primary = new BClipboard ("primary");
secondary = new BClipboard ("secondary");
}
+
+int
+be_enum_message (void *message, int32 *tc, int32 index,
+ int32 *count, const char **name_return)
+{
+ BMessage *msg = (BMessage *) message;
+ type_code type;
+ char *name;
+ status_t rc;
+
+ rc = msg->GetInfo (B_ANY_TYPE, index, &name, &type, count);
+
+ if (rc != B_OK)
+ return 1;
+
+ *tc = type;
+ *name_return = name;
+ return 0;
+}
+
+int
+be_get_refs_data (void *message, const char *name,
+ int32 index, char **path_buffer)
+{
+ status_t rc;
+ BEntry entry;
+ BPath path;
+ entry_ref ref;
+ BMessage *msg;
+
+ msg = (BMessage *) message;
+ rc = msg->FindRef (name, index, &ref);
+
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.SetTo (&ref, 0);
+
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.GetPath (&path);
+
+ if (rc != B_OK)
+ return 1;
+
+ *path_buffer = strdup (path.Path ());
+ return 0;
+}
+
+int
+be_get_message_data (void *message, const char *name,
+ int32 type_code, int32 index,
+ const void **buf_return,
+ ssize_t *size_return)
+{
+ BMessage *msg = (BMessage *) message;
+
+ return msg->FindData (name, type_code,
+ index, buf_return, size_return) != B_OK;
+}
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 4bd801242af..884e3583e25 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -381,37 +381,6 @@ public:
haiku_write (APP_QUIT_REQUESTED_EVENT, &rq);
return 0;
}
-
- void
- RefsReceived (BMessage *msg)
- {
- struct haiku_refs_event rq;
- entry_ref ref;
- BEntry entry;
- BPath path;
- int32 cookie = 0;
- int32 x, y;
- void *window;
-
- if ((msg->FindPointer ("window", 0, &window) != B_OK)
- || (msg->FindInt32 ("x", 0, &x) != B_OK)
- || (msg->FindInt32 ("y", 0, &y) != B_OK))
- return;
-
- rq.window = window;
- rq.x = x;
- rq.y = y;
-
- while (msg->FindRef ("refs", cookie++, &ref) == B_OK)
- {
- if (entry.SetTo (&ref, 0) == B_OK
- && entry.GetPath (&path) == B_OK)
- {
- rq.ref = strdup (path.Path ());
- haiku_write (REFS_EVENT, &rq);
- }
- }
- }
};
class EmacsWindow : public BWindow
@@ -665,21 +634,19 @@ public:
if (msg->WasDropped ())
{
- entry_ref ref;
BPoint whereto;
+ struct haiku_drag_and_drop_event rq;
- if (msg->FindRef ("refs", &ref) == B_OK)
+ if (msg->FindPoint ("_drop_point_", &whereto) == B_OK)
{
- msg->what = B_REFS_RECEIVED;
- msg->AddPointer ("window", this);
- if (msg->FindPoint ("_drop_point_", &whereto) == B_OK)
- {
- this->ConvertFromScreen (&whereto);
- msg->AddInt32 ("x", whereto.x);
- msg->AddInt32 ("y", whereto.y);
- }
- be_app->PostMessage (msg);
- msg->SendReply (B_OK);
+ this->ConvertFromScreen (&whereto);
+
+ rq.window = this;
+ rq.message = DetachCurrentMessage ();;
+ rq.x = whereto.x;
+ rq.y = whereto.y;
+
+ haiku_write (DRAG_AND_DROP_EVENT, &rq);
}
}
else if (msg->GetPointer ("menuptr"))
@@ -3897,3 +3864,9 @@ EmacsWindow_signal_menu_update_complete (void *window)
pthread_cond_signal (&w->menu_update_cv);
pthread_mutex_unlock (&w->menu_update_mutex);
}
+
+void
+BMessage_delete (void *message)
+{
+ delete (BMessage *) message;
+}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 41bd1e1c84f..78d51b83d8b 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -86,7 +86,7 @@ enum haiku_event_type
FILE_PANEL_EVENT,
MENU_BAR_HELP_EVENT,
ZOOM_EVENT,
- REFS_EVENT,
+ DRAG_AND_DROP_EVENT,
APP_QUIT_REQUESTED_EVENT,
DUMMY_EVENT,
MENU_BAR_LEFT
@@ -113,12 +113,11 @@ struct haiku_expose_event
int height;
};
-struct haiku_refs_event
+struct haiku_drag_and_drop_event
{
void *window;
int x, y;
- /* Free this with free! */
- char *ref;
+ void *message;
};
struct haiku_app_quit_requested_event
@@ -943,6 +942,9 @@ extern "C"
extern void
BWindow_dimensions (void *window, int *width, int *height);
+ extern void
+ BMessage_delete (void *message);
+
#ifdef __cplusplus
extern void *
find_appropriate_view_for_draw (void *vw);
diff --git a/src/haikuselect.c b/src/haikuselect.c
index 65dac0e02fa..f291fa70edd 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -179,6 +179,138 @@ same as `SECONDARY'. */)
return value ? Qt : Qnil;
}
+/* Return the Lisp representation of MESSAGE.
+
+ It is an alist of strings, denoting message parameter names, to a
+ list the form (TYPE . (DATA ...)), where TYPE is an integer
+ denoting the system data type of DATA, and DATA is in the general
+ case a unibyte string.
+
+ If TYPE is a symbol instead of an integer, then DATA was specially
+ decoded. If TYPE is `ref', then DATA is the absolute file name of
+ a file, or nil if decoding the file name failed. If TYPE is
+ `string', then DATA is a unibyte string. If TYPE is `short', then
+ DATA is a 16-bit signed integer. If TYPE is `long', then DATA is a
+ 32-bit signed integer. If TYPE is `llong', then DATA is a 64-bit
+ signed integer. If TYPE is `byte' or `char', then DATA is an 8-bit
+ signed integer. If TYPE is `bool', then DATA is a boolean. */
+Lisp_Object
+haiku_message_to_lisp (void *message)
+{
+ Lisp_Object list = Qnil, tem, t1, t2;
+ const char *name;
+ char *pbuf;
+ const void *buf;
+ ssize_t buf_size;
+ int32 i, j, count, type_code;
+ int rc;
+
+ for (i = 0; !be_enum_message (message, &type_code, i,
+ &count, &name); ++i)
+ {
+ tem = Qnil;
+
+ for (j = 0; j < count; ++j)
+ {
+ rc = be_get_message_data (message, name,
+ type_code, j,
+ &buf, &buf_size);
+ if (rc)
+ emacs_abort ();
+
+ switch (type_code)
+ {
+ case 'BOOL':
+ t1 = (*(bool *) buf) ? Qt : Qnil;
+ break;
+
+ case 'RREF':
+ rc = be_get_refs_data (message, name,
+ j, &pbuf);
+
+ if (rc)
+ {
+ t1 = Qnil;
+ break;
+ }
+
+ if (!pbuf)
+ memory_full (SIZE_MAX);
+
+ t1 = build_string (pbuf);
+ free (pbuf);
+ break;
+
+ case 'SHRT':
+ t1 = make_fixnum (*(int16 *) buf);
+ break;
+
+ case 'LONG':
+ t1 = make_int (*(int32 *) buf);
+ break;
+
+ case 'LLNG':
+ t1 = make_int ((intmax_t) *(int64 *) buf);
+ break;
+
+ case 'BYTE':
+ case 'CHAR':
+ t1 = make_fixnum (*(int8 *) buf);
+ break;
+
+ default:
+ t1 = make_uninit_string (buf_size);
+ memcpy (SDATA (t1), buf, buf_size);
+ }
+
+ tem = Fcons (t1, tem);
+ }
+
+ switch (type_code)
+ {
+ case 'CSTR':
+ t2 = Qstring;
+ break;
+
+ case 'SHRT':
+ t2 = Qshort;
+ break;
+
+ case 'LONG':
+ t2 = Qlong;
+ break;
+
+ case 'LLNG':
+ t2 = Qllong;
+ break;
+
+ case 'BYTE':
+ t2 = Qbyte;
+ break;
+
+ case 'RREF':
+ t2 = Qref;
+ break;
+
+ case 'CHAR':
+ t2 = Qchar;
+ break;
+
+ case 'BOOL':
+ t2 = Qbool;
+ break;
+
+ default:
+ t2 = make_int (type_code);
+ }
+
+ tem = Fcons (t2, tem);
+ list = Fcons (Fcons (build_string_from_utf8 (name), tem), list);
+ }
+
+ return list;
+}
+
void
syms_of_haikuselect (void)
{
@@ -188,6 +320,14 @@ syms_of_haikuselect (void)
DEFSYM (QUTF8_STRING, "UTF8_STRING");
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (QTARGETS, "TARGETS");
+ DEFSYM (Qstring, "string");
+ DEFSYM (Qref, "ref");
+ DEFSYM (Qshort, "short");
+ DEFSYM (Qlong, "long");
+ DEFSYM (Qllong, "llong");
+ DEFSYM (Qbyte, "byte");
+ DEFSYM (Qchar, "char");
+ DEFSYM (Qbool, "bool");
defsubr (&Shaiku_selection_data);
defsubr (&Shaiku_selection_put);
diff --git a/src/haikuselect.h b/src/haikuselect.h
index 566aae596f6..14b779c36dc 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -23,6 +23,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <cstdio>
#endif
+#include <SupportDefs.h>
+
#ifdef __cplusplus
#include <stdio.h>
extern "C"
@@ -72,11 +74,19 @@ extern "C"
extern bool
BClipboard_owns_primary (void);
- extern bool
- BClipboard_owns_secondary (void);
+ extern bool BClipboard_owns_secondary (void);
/* Free the returned data. */
extern void BClipboard_free_data (void *ptr);
+
+ extern int be_enum_message (void *message, int32 *tc, int index,
+ int32 *count, const char **name_return);
+ extern int be_get_message_data (void *message, const char *name,
+ int32 type_code, int32 index,
+ const void **buf_return,
+ ssize_t *size_return);
+ extern int be_get_refs_data (void *message, const char *name,
+ int32 index, char **path_buffer);
#ifdef __cplusplus
};
#endif
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 52846fc1450..9844a09a024 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3545,27 +3545,25 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
haiku_make_fullscreen_consistent (f);
break;
}
- case REFS_EVENT:
+ case DRAG_AND_DROP_EVENT:
{
- struct haiku_refs_event *b = buf;
+ struct haiku_drag_and_drop_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
if (!f)
{
- free (b->ref);
+ BMessage_delete (b->message);
continue;
}
inev.kind = DRAG_N_DROP_EVENT;
- inev.arg = build_string_from_utf8 (b->ref);
+ inev.arg = haiku_message_to_lisp (b->message);
XSETINT (inev.x, b->x);
XSETINT (inev.y, b->y);
XSETFRAME (inev.frame_or_window, f);
- /* There should be no problem with calling free here.
- free on Haiku is thread-safe. */
- free (b->ref);
+ BMessage_delete (b->message);
break;
}
case APP_QUIT_REQUESTED_EVENT:
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 64fd0ec2b71..8d0af8dc679 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -255,6 +255,7 @@ extern void haiku_free_frame_resources (struct frame *f);
extern void haiku_scroll_bar_remove (struct scroll_bar *bar);
extern void haiku_clear_under_internal_border (struct frame *f);
extern void haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p);
+extern Lisp_Object haiku_message_to_lisp (void *);
extern struct haiku_display_info *haiku_term_init (void);