(executable-find (car cmd)))
(throw 'found cmd)))))
+(declare-function haiku-set-wallpaper "term/haiku-win.el")
+
(defun wallpaper-set (file)
"Set the desktop background to FILE in a graphical environment."
(interactive (list (and
(unless (file-readable-p file)
(error "File is not readable: %s" file))
(when (display-graphic-p)
- (let* ((command (wallpaper--find-command))
- (fmt-spec `((?f . ,(expand-file-name file))
- (?h . ,(display-pixel-height))
- (?w . ,(display-pixel-width))))
- (bufname (format " *wallpaper-%s*" (random)))
- (process
- (and command
- (apply #'start-process "set-wallpaper" bufname
- (car command)
- (mapcar (lambda (arg) (format-spec arg fmt-spec))
- (cdr command))))))
- (unless command
- (error "Can't find a suitable command for setting the wallpaper"))
- (wallpaper-debug "Using command %s" (car command))
- (setf (process-sentinel process)
- (lambda (process status)
- (unwind-protect
- (unless (and (eq (process-status process) 'exit)
- (zerop (process-exit-status process)))
- (message "command %S %s: %S" (string-join (process-command process) " ")
- (string-replace "\n" "" status)
- (with-current-buffer (process-buffer process)
- (string-clean-whitespace (buffer-string)))))
- (ignore-errors
- (kill-buffer (process-buffer process))))))
- process)))
+ (if (featurep 'haiku)
+ (haiku-set-wallpaper file)
+ (let* ((command (wallpaper--find-command))
+ (fmt-spec `((?f . ,(expand-file-name file))
+ (?h . ,(display-pixel-height))
+ (?w . ,(display-pixel-width))))
+ (bufname (format " *wallpaper-%s*" (random)))
+ (process
+ (and command
+ (apply #'start-process "set-wallpaper" bufname
+ (car command)
+ (mapcar (lambda (arg) (format-spec arg fmt-spec))
+ (cdr command))))))
+ (unless command
+ (error "Can't find a suitable command for setting the wallpaper"))
+ (wallpaper-debug "Using command %s" (car command))
+ (setf (process-sentinel process)
+ (lambda (process status)
+ (unwind-protect
+ (unless (and (eq (process-status process) 'exit)
+ (zerop (process-exit-status process)))
+ (message "command %S %s: %S" (string-join (process-command process) " ")
+ (string-replace "\n" "" status)
+ (with-current-buffer (process-buffer process)
+ (string-clean-whitespace (buffer-string)))))
+ (ignore-errors
+ (kill-buffer (process-buffer process))))))
+ process))))
(provide 'wallpaper)
;; the Deskbar will not, so kill ourself here.
(unless cancel-shutdown (kill-emacs))))
+;;;; Wallpaper support.
+\f
+
+(declare-function haiku-write-node-attribute "haikuselect.c")
+(declare-function haiku-send-message "haikuselect.c")
+
+(defun haiku-set-wallpaper (file)
+ "Make FILE the wallpaper.
+Set the desktop background to the image FILE, on all workspaces,
+with an offset of 0, 0."
+ (let ((encoded-file (encode-coding-string
+ (expand-file-name file)
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ ;; Write the necessary information to the desktop directory.
+ (haiku-write-node-attribute "/boot/home/Desktop"
+ "be:bgndimginfo"
+ (list '(type . 0)
+ '("be:bgndimginfoerasetext" bool t)
+ (list "be:bgndimginfopath" 'string
+ encoded-file)
+ '("be:bgndimginfoworkspaces" long
+ ;; This is a mask of all the
+ ;; workspaces the background
+ ;; image will be applied to. It
+ ;; is treated as an unsigned
+ ;; value by the Tracker, despite
+ ;; the type being signed.
+ -1)
+ ;; Don't apply an offset
+ '("be:bgndimginfooffset" point (0 . 0))
+ ;; Don't stretch or crop or anything
+ '("be:bgndimginfomode" long 0)
+ ;; Don't apply a set
+ '("be:bgndimginfoset" long 0)))
+ ;; Tell the tracker to redisplay the wallpaper.
+ (haiku-send-message "application/x-vnd.Be-TRAK"
+ (list (cons 'type (haiku-numeric-enum Tbgr))))))
+
\f
;;;; Cursors.
#include <game/WindowScreen.h>
#include <game/DirectWindow.h>
+#include <storage/FindDirectory.h>
#include <storage/Entry.h>
#include <storage/Path.h>
#include <storage/FilePanel.h>
#include <storage/AppFileInfo.h>
#include <storage/Path.h>
#include <storage/PathFinder.h>
+#include <storage/Node.h>
#include <support/Beep.h>
#include <support/DataIO.h>
vw = (EmacsView *) view;
vw->SetFrameSynchronization (sync);
}
+
+status_t
+be_write_node_message (const char *path, const char *name, void *message)
+{
+ BNode node (path);
+ status_t rc;
+ ssize_t flat, result;
+ char *buffer;
+ BMessage *msg;
+
+ rc = node.InitCheck ();
+ msg = (BMessage *) message;
+
+ if (rc < B_OK)
+ return rc;
+
+ flat = msg->FlattenedSize ();
+ if (flat < B_OK)
+ return flat;
+
+ buffer = new (std::nothrow) char[flat];
+ if (!buffer)
+ return B_NO_MEMORY;
+
+ rc = msg->Flatten (buffer, flat);
+ if (rc < B_OK)
+ {
+ delete[] buffer;
+ return rc;
+ }
+
+ result = node.WriteAttr (name, B_MIME_TYPE, 0,
+ buffer, flat);
+ delete[] buffer;
+
+ if (result < B_OK)
+ return result;
+
+ if (result != flat)
+ return B_ERROR;
+
+ return B_OK;
+}
+
+void
+be_send_message (const char *app_id, void *message)
+{
+ BMessenger messenger (app_id);
+
+ messenger.SendMessage ((BMessage *) message);
+}
extern void be_send_move_frame_event (void *);
extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode);
+extern status_t be_write_node_message (const char *, const char *, void *);
+extern void be_send_message (const char *, void *);
+
extern void be_lock_window (void *);
extern void be_unlock_window (void *);
extern bool be_get_explicit_workarea (int *, int *, int *, int *);
t1 = make_float (*(float *) buf);
break;
+ case 'CSTR':
+ /* Is this even possible? */
+ if (!buf_size)
+ buf_size = 1;
+
+ t1 = make_uninit_string (buf_size - 1);
+ memcpy (SDATA (t1), buf, buf_size - 1);
+ break;
+
default:
t1 = make_uninit_string (buf_size);
memcpy (SDATA (t1), buf, buf_size);
signal_error ("Failed to add bool", data);
break;
+ case 'CSTR':
+ /* C strings must be handled specially, since they
+ include a trailing NULL byte. */
+ CHECK_STRING (data);
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, SDATA (data),
+ SBYTES (data) + 1);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add", data);
+ break;
+
default:
decode_normally:
CHECK_STRING (data);
BMessage_delete (message);
}
+static void
+haiku_report_system_error (status_t code, const char *format)
+{
+ switch (code)
+ {
+ case B_BAD_VALUE:
+ error (format, "Bad value");
+ break;
+
+ case B_ENTRY_NOT_FOUND:
+ error (format, "File not found");
+ break;
+
+ case B_PERMISSION_DENIED:
+ error (format, "Permission denied");
+ break;
+
+ case B_LINK_LIMIT:
+ error (format, "Link limit reached");
+ break;
+
+ case B_BUSY:
+ error (format, "Device busy");
+ break;
+
+ case B_NO_MORE_FDS:
+ error (format, "No more file descriptors");
+ break;
+
+ case B_FILE_ERROR:
+ error (format, "File error");
+ break;
+
+ case B_NO_MEMORY:
+ memory_full (SIZE_MAX);
+ break;
+
+ default:
+ error (format, "Unknown error");
+ break;
+ }
+}
+
DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message,
2, 4, 0,
doc: /* Begin dragging MESSAGE from FRAME.
return SAFE_FREE_UNBIND_TO (depth, Qnil);
}
+DEFUN ("haiku-write-node-attribute", Fhaiku_write_node_attribute,
+ Shaiku_write_node_attribute, 3, 3, 0,
+ doc: /* Write a message as a file-system attribute of NODE.
+FILE should be a file name of a file on a Be File System volume, NAME
+should be a string describing the name of the attribute that will be
+written, and MESSAGE will be the attribute written to FILE, as a
+system message in the format accepted by `haiku-drag-message', which
+see. */)
+ (Lisp_Object file, Lisp_Object name, Lisp_Object message)
+{
+ void *be_message;
+ status_t rc;
+ specpdl_ref count;
+
+ CHECK_STRING (file);
+ CHECK_STRING (name);
+
+ file = ENCODE_FILE (file);
+ name = ENCODE_SYSTEM (name);
+
+ be_message = be_create_simple_message ();
+ count = SPECPDL_INDEX ();
+
+ record_unwind_protect_ptr (BMessage_delete, be_message);
+ haiku_lisp_to_message (message, be_message);
+ rc = be_write_node_message (SSDATA (file), SSDATA (name),
+ be_message);
+
+ if (rc < B_OK)
+ haiku_report_system_error (rc, "Failed to set attribute: %s");
+
+ return unbind_to (count, Qnil);
+}
+
+DEFUN ("haiku-send-message", Fhaiku_send_message, Shaiku_send_message,
+ 2, 2, 0,
+ doc: /* Send a system message to PROGRAM.
+PROGRAM must be the name of the application to which the message will
+be sent. MESSAGE is the system message, serialized in the format
+accepted by `haiku-drag-message', that will be sent to the application
+specified by PROGRAM. There is no guarantee that the message will
+arrive after this function is called. */)
+ (Lisp_Object program, Lisp_Object message)
+{
+ specpdl_ref count;
+ void *be_message;
+
+ CHECK_STRING (program);
+ program = ENCODE_SYSTEM (program);
+
+ be_message = be_create_simple_message ();
+ count = SPECPDL_INDEX ();
+
+ record_unwind_protect_ptr (BMessage_delete, be_message);
+ haiku_lisp_to_message (message, be_message);
+ be_send_message (SSDATA (program), be_message);
+
+ return unbind_to (count, Qnil);
+}
+
static void
haiku_dnd_compute_tip_xy (int *root_x, int *root_y)
{
defsubr (&Shaiku_selection_owner_p);
defsubr (&Shaiku_drag_message);
defsubr (&Shaiku_roster_launch);
+ defsubr (&Shaiku_write_node_attribute);
+ defsubr (&Shaiku_send_message);
haiku_dnd_frame = NULL;
}