summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-04 03:23:11 +0000
committerPo Lu <luangruo@yahoo.com>2022-05-04 03:23:11 +0000
commitb5cf6c1ab6cc5ca3d7a4b5d1e2b775d7d59a5866 (patch)
treec0728c027deb2b081d5df57c2a1fe54cfb3cfb4b
parent7dfb068c13205df9e58d289c3fb4ddafd8625600 (diff)
downloademacs-b5cf6c1ab6cc5ca3d7a4b5d1e2b775d7d59a5866.tar.gz
Clean up Haiku file panel code
* lisp/term/haiku-win.el (x-file-dialog): Fix nil values of `default-filename'. * src/haiku_io.c (haiku_len): Remove `FILE_PANEL_EVENT'. (record_c_unwind_protect_from_cxx, c_specpdl_idx_from_cxx) (c_unbind_to_nil_from_cxx): Delete functions. * src/haiku_support.cc (MessageReceived): Write pointer to buffer to file panel port instead. (struct popup_file_dialog_data): Delete strict. (unwind_popup_file_dialog): Delete functions. (be_popup_file_dialog): Accept a pointer to `process_pending_signals' and run nested event loop as usual. * src/haiku_support.h (enum haiku_event_type): Remove `FILE_PANEL_EVENT'. (struct haiku_file_panel_event): Delete struct. * src/haikufns.c (unwind_popup): Delete function. (Fhaiku_read_file_name): Update and quit on invalid filename. * src/haikuterm.c (struct unhandled_event): Delete struct. (haiku_read_socket): Remove "unhandled events".
-rw-r--r--lisp/term/haiku-win.el3
-rw-r--r--src/haiku_io.c23
-rw-r--r--src/haiku_support.cc176
-rw-r--r--src/haiku_support.h13
-rw-r--r--src/haikufns.c64
-rw-r--r--src/haikuterm.c30
6 files changed, 116 insertions, 193 deletions
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index 09210792468..5f020877325 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -273,7 +273,8 @@ or a pair of markers) and turns it into a file system reference."
(or dir (and default-filename
(file-name-directory default-filename)))
mustmatch only-dir-p
- (file-name-nondirectory default-filename))
+ (and default-filename
+ (file-name-nondirectory default-filename)))
(error "x-file-dialog on a tty frame")))
(defun haiku-drag-and-drop (event)
diff --git a/src/haiku_io.c b/src/haiku_io.c
index 0db5d26314b..5d0031ef712 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -91,8 +91,6 @@ haiku_len (enum haiku_event_type type)
return sizeof (struct haiku_menu_bar_state_event);
case MENU_BAR_SELECT_EVENT:
return sizeof (struct haiku_menu_bar_select_event);
- case FILE_PANEL_EVENT:
- return sizeof (struct haiku_file_panel_event);
case MENU_BAR_HELP_EVENT:
return sizeof (struct haiku_menu_bar_help_event);
case ZOOM_EVENT:
@@ -209,24 +207,3 @@ haiku_io_init_in_app_thread (void)
if (pthread_sigmask (SIG_BLOCK, &set, NULL))
perror ("pthread_sigmask");
}
-
-/* Record an unwind protect from C++ code. */
-void
-record_c_unwind_protect_from_cxx (void (*fn) (void *), void *r)
-{
- record_unwind_protect_ptr (fn, r);
-}
-
-/* SPECPDL_IDX that is safe from C++ code. */
-specpdl_ref
-c_specpdl_idx_from_cxx (void)
-{
- return SPECPDL_INDEX ();
-}
-
-/* unbind_to (IDX, Qnil), but safe from C++ code. */
-void
-c_unbind_to_nil_from_cxx (specpdl_ref idx)
-{
- unbind_to (idx, Qnil);
-}
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 80c3ba3331d..1280a77b22a 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -100,6 +100,7 @@ enum
REPLAY_MENU_BAR = 3007,
FONT_FAMILY_SELECTED = 3008,
FONT_STYLE_SELECTED = 3009,
+ FILE_PANEL_SELECTION = 3010,
};
/* X11 keysyms that we use. */
@@ -188,6 +189,10 @@ static void *grab_view = NULL;
static BLocker grab_view_locker;
static bool drag_and_drop_in_progress;
+/* Port used to send data to the main thread while a file panel is
+ active. */
+static port_id volatile current_file_panel_port;
+
/* Many places require us to lock the child frame data, and then lock
the locker of some random window. Unfortunately, locking such a
window might be delayed due to an arriving message, which then
@@ -875,46 +880,48 @@ public:
haiku_write (MENU_BAR_SELECT_EVENT, &rq);
}
- else if (msg->what == 'FPSE'
+ else if (msg->what == FILE_PANEL_SELECTION
|| ((msg->FindInt32 ("old_what", &old_what) == B_OK
- && old_what == 'FPSE')))
+ && old_what == FILE_PANEL_SELECTION)))
{
- struct haiku_file_panel_event rq;
+ const char *str_path, *name;
+ char *file_name, *str_buf;
BEntry entry;
BPath path;
entry_ref ref;
- rq.ptr = NULL;
+ file_name = NULL;
if (msg->FindRef ("refs", &ref) == B_OK &&
entry.SetTo (&ref, 0) == B_OK &&
entry.GetPath (&path) == B_OK)
{
- const char *str_path = path.Path ();
+ str_path = path.Path ();
+
if (str_path)
- rq.ptr = strdup (str_path);
+ file_name = strdup (str_path);
}
if (msg->FindRef ("directory", &ref),
entry.SetTo (&ref, 0) == B_OK &&
entry.GetPath (&path) == B_OK)
{
- const char *name = msg->GetString ("name");
- const char *str_path = path.Path ();
+ name = msg->GetString ("name");
+ str_path = path.Path ();
if (name)
{
- char str_buf[std::strlen (str_path)
- + std::strlen (name) + 2];
- snprintf ((char *) &str_buf,
- std::strlen (str_path)
+ str_buf = (char *) alloca (std::strlen (str_path)
+ + std::strlen (name) + 2);
+ snprintf (str_buf, std::strlen (str_path)
+ std::strlen (name) + 2, "%s/%s",
str_path, name);
- rq.ptr = strdup (str_buf);
+ file_name = strdup (str_buf);
}
}
- haiku_write (FILE_PANEL_EVENT, &rq);
+ write_port (current_file_panel_port, 0,
+ &file_name, sizeof file_name);
}
else
BWindow::MessageReceived (msg);
@@ -1117,12 +1124,13 @@ public:
void
Minimize (bool minimized_p)
{
- BWindow::Minimize (minimized_p);
struct haiku_iconification_event rq;
+
rq.window = this;
rq.iconified_p = !parent && minimized_p;
-
haiku_write (ICONIFICATION, &rq);
+
+ BWindow::Minimize (minimized_p);
}
void
@@ -4121,100 +4129,92 @@ EmacsView_double_buffered_p (void *vw)
return db_p;
}
-struct popup_file_dialog_data
-{
- BMessage *msg;
- BFilePanel *panel;
- BEntry *entry;
-};
-
-static void
-unwind_popup_file_dialog (void *ptr)
-{
- struct popup_file_dialog_data *data
- = (struct popup_file_dialog_data *) ptr;
- BFilePanel *panel = data->panel;
-
- delete panel;
- delete data->entry;
- delete data->msg;
-}
-
/* Popup a file dialog. */
char *
be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
int dir_only_p, void *window, const char *save_text,
- const char *prompt, void (*block_input_function) (void),
- void (*unblock_input_function) (void),
- void (*maybe_quit_function) (void))
-{
- specpdl_ref idx = c_specpdl_idx_from_cxx ();
- /* setjmp/longjmp is UB with automatic objects. */
- BWindow *w = (BWindow *) window;
- uint32_t mode = (dir_only_p
- ? B_DIRECTORY_NODE
- : B_FILE_NODE | B_DIRECTORY_NODE);
- BEntry *path = new BEntry;
- BMessage *msg = new BMessage ('FPSE');
- BFilePanel *panel = new BFilePanel (open_p ? B_OPEN_PANEL : B_SAVE_PANEL,
- NULL, NULL, mode);
- void *buf;
- enum haiku_event_type type;
- char *ptr;
- struct popup_file_dialog_data dat;
- ssize_t b_s;
-
- dat.entry = path;
- dat.msg = msg;
- dat.panel = panel;
-
- record_c_unwind_protect_from_cxx (unwind_popup_file_dialog, &dat);
+ const char *prompt,
+ void (*process_pending_signals_function) (void))
+{
+ BWindow *w, *panel_window;
+ BEntry path;
+ BMessage msg (FILE_PANEL_SELECTION);
+ BFilePanel panel (open_p ? B_OPEN_PANEL : B_SAVE_PANEL,
+ NULL, NULL, (dir_only_p
+ ? B_DIRECTORY_NODE
+ : B_FILE_NODE | B_DIRECTORY_NODE));
+ object_wait_info infos[2];
+ ssize_t status;
+ int32 reply_type;
+ char *file_name;
+
+ current_file_panel_port = create_port (1, "file panel port");
+ file_name = NULL;
+
+ if (current_file_panel_port < B_OK)
+ return NULL;
if (default_dir)
{
- if (path->SetTo (default_dir, 0) != B_OK)
+ if (path.SetTo (default_dir, 0) != B_OK)
default_dir = NULL;
}
- panel->SetMessage (msg);
+ w = (BWindow *) window;
+ panel_window = panel.Window ();
+
+ panel.SetMessage (&msg);
if (default_dir)
- panel->SetPanelDirectory (path);
+ panel.SetPanelDirectory (&path);
+
if (save_text)
- panel->SetSaveText (save_text);
+ panel.SetSaveText (save_text);
- panel->SetHideWhenDone (0);
- panel->Window ()->SetTitle (prompt);
- panel->SetTarget (BMessenger (w));
- panel->Show ();
+ panel_window->SetTitle (prompt);
+ panel_window->SetFeel (B_MODAL_APP_WINDOW_FEEL);
- buf = alloca (200);
- while (1)
+ panel.SetHideWhenDone (false);
+ panel.SetTarget (BMessenger (w));
+ panel.Show ();
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = current_file_panel_port;
+ infos[1].type = B_OBJECT_TYPE_PORT;
+ infos[1].events = B_EVENT_READ;
+
+ while (true)
{
- ptr = NULL;
+ status = wait_for_objects (infos, 2);
- if (!haiku_read_with_timeout (&type, buf, 200, 1000000, false))
- {
- block_input_function ();
- if (type != FILE_PANEL_EVENT)
- haiku_write (type, buf);
- else if (!ptr)
- ptr = (char *) ((struct haiku_file_panel_event *) buf)->ptr;
- unblock_input_function ();
+ if (status == B_INTERRUPTED || status == B_WOULD_BLOCK)
+ continue;
- maybe_quit_function ();
- }
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
- block_input_function ();
- haiku_read_size (&b_s, false);
- if (!b_s || ptr || panel->Window ()->IsHidden ())
+ if (infos[1].events & B_EVENT_READ)
{
- c_unbind_to_nil_from_cxx (idx);
- unblock_input_function ();
- return ptr;
+ status = read_port (current_file_panel_port,
+ &reply_type, &file_name,
+ sizeof file_name);
+
+ if (status < B_OK)
+ file_name = NULL;
+
+ goto out;
}
- unblock_input_function ();
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_READ;
}
+
+ out:
+ delete_port (current_file_panel_port);
+ return file_name;
}
/* Zoom WINDOW. */
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 056063864e1..722c05511cf 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -91,7 +91,6 @@ enum haiku_event_type
MENU_BAR_OPEN,
MENU_BAR_SELECT_EVENT,
MENU_BAR_CLOSE,
- FILE_PANEL_EVENT,
MENU_BAR_HELP_EVENT,
ZOOM_EVENT,
DRAG_AND_DROP_EVENT,
@@ -222,11 +221,6 @@ struct haiku_menu_bar_select_event
void *ptr;
};
-struct haiku_file_panel_event
-{
- void *ptr;
-};
-
struct haiku_menu_bar_help_event
{
void *window;
@@ -612,12 +606,7 @@ extern int EmacsView_double_buffered_p (void *);
extern char *be_popup_file_dialog (int, const char *, int,
int, void *, const char *,
- const char *, void (*) (void),
- void (*) (void), void (*) (void));
-
-extern void record_c_unwind_protect_from_cxx (void (*) (void *), void *);
-extern specpdl_ref c_specpdl_idx_from_cxx (void);
-extern void c_unbind_to_nil_from_cxx (specpdl_ref);
+ const char *, void (*) (void));
#ifdef HAVE_NATIVE_IMAGE_API
extern int be_can_translate_type_to_bitmap_p (const char *);
diff --git a/src/haikufns.c b/src/haikufns.c
index 78014c50886..3e3104193e0 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -617,14 +617,6 @@ haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval
}
}
-static void
-unwind_popup (void)
-{
- if (!popup_activated_p)
- emacs_abort ();
- --popup_activated_p;
-}
-
static Lisp_Object
haiku_create_frame (Lisp_Object parms)
{
@@ -2479,12 +2471,15 @@ Optional arg MUSTMATCH, if non-nil, means the returned file or
directory must exist.
Optional arg DIR_ONLY_P, if non-nil, means choose only directories.
Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry field. */)
- (Lisp_Object prompt, Lisp_Object frame,
- Lisp_Object dir, Lisp_Object mustmatch,
- Lisp_Object dir_only_p, Lisp_Object save_text)
+ (Lisp_Object prompt, Lisp_Object frame, Lisp_Object dir,
+ Lisp_Object mustmatch, Lisp_Object dir_only_p, Lisp_Object save_text)
{
- if (!x_display_list)
- error ("Haiku windowing not initialized");
+ struct frame *f;
+ char *file_name;
+ Lisp_Object value;
+
+ if (popup_activated_p)
+ error ("Trying to use a menu from within a menu-entry");
if (!NILP (dir))
CHECK_STRING (dir);
@@ -2497,37 +2492,28 @@ Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry fie
CHECK_STRING (prompt);
- CHECK_LIVE_FRAME (frame);
- check_window_system (XFRAME (frame));
-
- specpdl_ref idx = SPECPDL_INDEX ();
- record_unwind_protect_void (unwind_popup);
-
- struct frame *f = XFRAME (frame);
-
- FRAME_DISPLAY_INFO (f)->focus_event_frame = f;
+ f = decode_window_system_frame (frame);
++popup_activated_p;
- char *fn = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
- !NILP (dir) ? SSDATA (ENCODE_UTF_8 (dir)) : NULL,
- !NILP (mustmatch), !NILP (dir_only_p),
- FRAME_HAIKU_WINDOW (f),
- !NILP (save_text) ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL,
- SSDATA (ENCODE_UTF_8 (prompt)),
- block_input, unblock_input, maybe_quit);
-
- unbind_to (idx, Qnil);
+ unrequest_sigio ();
+ file_name = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
+ !NILP (dir) ? SSDATA (dir) : NULL,
+ !NILP (mustmatch), !NILP (dir_only_p),
+ FRAME_HAIKU_WINDOW (f),
+ (!NILP (save_text)
+ ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL),
+ SSDATA (ENCODE_UTF_8 (prompt)),
+ process_pending_signals);
+ request_sigio ();
+ --popup_activated_p;
- block_input ();
- BWindow_activate (FRAME_HAIKU_WINDOW (f));
- unblock_input ();
+ if (!file_name)
+ quit ();
- if (!fn)
- return Qnil;
+ value = build_string (file_name);
+ free (file_name);
- Lisp_Object p = build_string_from_utf8 (fn);
- free (fn);
- return p;
+ return value;
}
DEFUN ("haiku-put-resource", Fhaiku_put_resource, Shaiku_put_resource,
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 80c945c7724..341288133e8 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -54,14 +54,6 @@ static void **fringe_bmps;
static int max_fringe_bmp = 0;
static Lisp_Object rdb;
-
-struct unhandled_event
-{
- struct unhandled_event *next;
- enum haiku_event_type type;
- uint8_t buffer[200];
-};
-
static bool any_help_event_p;
char *
@@ -2824,7 +2816,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
int message_count;
static void *buf;
ssize_t b_size;
- struct unhandled_event *unhandled_events = NULL;
int button_or_motion_p, do_help;
enum haiku_event_type type;
struct input_event inev, inev2;
@@ -3583,19 +3574,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
f->menu_bar_vector, b->ptr);
break;
}
- case FILE_PANEL_EVENT:
- {
- if (!popup_activated_p)
- continue;
-
- struct unhandled_event *ev = xmalloc (sizeof *ev);
- ev->next = unhandled_events;
- ev->type = type;
- memcpy (&ev->buffer, buf, 200);
-
- unhandled_events = ev;
- break;
- }
case MENU_BAR_HELP_EVENT:
{
struct haiku_menu_bar_help_event *b = buf;
@@ -3678,14 +3656,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
}
}
- for (struct unhandled_event *ev = unhandled_events; ev;)
- {
- haiku_write_without_signal (ev->type, &ev->buffer, false);
- struct unhandled_event *old = ev;
- ev = old->next;
- xfree (old);
- }
-
if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT))
{
Lisp_Object help_frame = Qnil;