mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-15 11:21:19 -07:00
* doc/lispref/frames.texi (Drag and Drop): Fix documentation of `x-begin-drag' to match actual function arity. * lisp/term/haiku-win.el (haiku-dnd-selection-value): New variable. (haiku-dnd-selection-converters): New variable. (haiku-dnd-convert-string): New function. (gui-backend-get-selection, gui-backend-set-selection): Handle XdndSelection specially. (x-begin-drag): New function. * src/haiku_select.cc (be_create_simple_message) (be_add_message_data): New functions. * src/haiku_support.cc (WAIT_FOR_RELEASE): New message type. (class EmacsView, MouseUp): If waiting for release, reply and drop event. (be_drag_message, be_drag_message_thread_entry): New functions. * src/haiku_support.h: Update prototypes. * src/haikuselect.c (lisp_to_type_code, haiku_lisp_to_message) (Fhaiku_drag_message): New functions. (syms_of_haikuselect): Define new subr. * src/haikuselect.h: Update prototypes.
339 lines
6.3 KiB
C++
339 lines
6.3 KiB
C++
/* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
|
|
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
GNU Emacs is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or (at
|
|
your option) any later version.
|
|
|
|
GNU Emacs is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
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>
|
|
|
|
#include "haikuselect.h"
|
|
|
|
|
|
static BClipboard *primary = NULL;
|
|
static BClipboard *secondary = NULL;
|
|
static BClipboard *system_clipboard = NULL;
|
|
static int64 count_clipboard = -1;
|
|
static int64 count_primary = -1;
|
|
static int64 count_secondary = -1;
|
|
|
|
int selection_state_flag;
|
|
|
|
static char *
|
|
BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len)
|
|
{
|
|
if (!cb->Lock ())
|
|
return 0;
|
|
|
|
BMessage *dat = cb->Data ();
|
|
if (!dat)
|
|
{
|
|
cb->Unlock ();
|
|
return 0;
|
|
}
|
|
|
|
const char *ptr;
|
|
ssize_t bt;
|
|
dat->FindData (type, B_MIME_TYPE, (const void **) &ptr, &bt);
|
|
|
|
if (!ptr)
|
|
{
|
|
cb->Unlock ();
|
|
return NULL;
|
|
}
|
|
|
|
if (len)
|
|
*len = bt;
|
|
|
|
cb->Unlock ();
|
|
|
|
return strndup (ptr, bt);
|
|
}
|
|
|
|
static void
|
|
BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size)
|
|
{
|
|
BMessage *data;
|
|
char *name;
|
|
int32 count_found;
|
|
type_code type;
|
|
int32 i;
|
|
int index;
|
|
|
|
if (!cb->Lock ())
|
|
{
|
|
buf[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
data = cb->Data ();
|
|
index = 0;
|
|
|
|
if (!data)
|
|
{
|
|
buf[0] = NULL;
|
|
cb->Unlock ();
|
|
return;
|
|
}
|
|
|
|
for (i = 0; (data->GetInfo (B_ANY_TYPE, i, &name,
|
|
&type, &count_found)
|
|
== B_OK); ++i)
|
|
{
|
|
if (type == B_MIME_TYPE)
|
|
{
|
|
if (index < (buf_size - 1))
|
|
{
|
|
buf[index++] = strdup (name);
|
|
|
|
if (!buf[index - 1])
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
buf[index] = NULL;
|
|
|
|
cb->Unlock ();
|
|
}
|
|
|
|
static void
|
|
BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
|
|
ssize_t len, bool clear)
|
|
{
|
|
if (!cb->Lock ())
|
|
return;
|
|
|
|
if (clear)
|
|
cb->Clear ();
|
|
|
|
BMessage *mdat = cb->Data ();
|
|
if (!mdat)
|
|
{
|
|
cb->Unlock ();
|
|
return;
|
|
}
|
|
|
|
if (dat)
|
|
{
|
|
if (mdat->ReplaceData (type, B_MIME_TYPE, dat, len)
|
|
== B_NAME_NOT_FOUND)
|
|
mdat->AddData (type, B_MIME_TYPE, dat, len);
|
|
}
|
|
else
|
|
mdat->RemoveName (type);
|
|
cb->Commit ();
|
|
cb->Unlock ();
|
|
}
|
|
|
|
char *
|
|
BClipboard_find_system_data (const char *type, ssize_t *len)
|
|
{
|
|
if (!system_clipboard)
|
|
return 0;
|
|
|
|
return BClipboard_find_data (system_clipboard, type, len);
|
|
}
|
|
|
|
char *
|
|
BClipboard_find_primary_selection_data (const char *type, ssize_t *len)
|
|
{
|
|
if (!primary)
|
|
return 0;
|
|
|
|
return BClipboard_find_data (primary, type, len);
|
|
}
|
|
|
|
char *
|
|
BClipboard_find_secondary_selection_data (const char *type, ssize_t *len)
|
|
{
|
|
if (!secondary)
|
|
return 0;
|
|
|
|
return BClipboard_find_data (secondary, type, len);
|
|
}
|
|
|
|
void
|
|
BClipboard_set_system_data (const char *type, const char *data,
|
|
ssize_t len, bool clear)
|
|
{
|
|
if (!system_clipboard)
|
|
return;
|
|
|
|
count_clipboard = system_clipboard->SystemCount ();
|
|
BClipboard_set_data (system_clipboard, type, data, len, clear);
|
|
}
|
|
|
|
void
|
|
BClipboard_set_primary_selection_data (const char *type, const char *data,
|
|
ssize_t len, bool clear)
|
|
{
|
|
if (!primary)
|
|
return;
|
|
|
|
count_primary = primary->SystemCount ();
|
|
BClipboard_set_data (primary, type, data, len, clear);
|
|
}
|
|
|
|
void
|
|
BClipboard_set_secondary_selection_data (const char *type, const char *data,
|
|
ssize_t len, bool clear)
|
|
{
|
|
if (!secondary)
|
|
return;
|
|
|
|
count_secondary = secondary->SystemCount ();
|
|
BClipboard_set_data (secondary, type, data, len, clear);
|
|
}
|
|
|
|
void
|
|
BClipboard_free_data (void *ptr)
|
|
{
|
|
std::free (ptr);
|
|
}
|
|
|
|
void
|
|
BClipboard_system_targets (char **buf, int len)
|
|
{
|
|
BClipboard_get_targets (system_clipboard, buf, len);
|
|
}
|
|
|
|
void
|
|
BClipboard_primary_targets (char **buf, int len)
|
|
{
|
|
BClipboard_get_targets (primary, buf, len);
|
|
}
|
|
|
|
void
|
|
BClipboard_secondary_targets (char **buf, int len)
|
|
{
|
|
BClipboard_get_targets (secondary, buf, len);
|
|
}
|
|
|
|
bool
|
|
BClipboard_owns_clipboard (void)
|
|
{
|
|
return (count_clipboard >= 0
|
|
&& (count_clipboard + 1
|
|
== system_clipboard->SystemCount ()));
|
|
}
|
|
|
|
bool
|
|
BClipboard_owns_primary (void)
|
|
{
|
|
return (count_primary >= 0
|
|
&& (count_primary + 1
|
|
== primary->SystemCount ()));
|
|
}
|
|
|
|
bool
|
|
BClipboard_owns_secondary (void)
|
|
{
|
|
return (count_secondary >= 0
|
|
&& (count_secondary + 1
|
|
== secondary->SystemCount ()));
|
|
}
|
|
|
|
void
|
|
init_haiku_select (void)
|
|
{
|
|
system_clipboard = new BClipboard ("system");
|
|
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;
|
|
}
|
|
|
|
void *
|
|
be_create_simple_message (void)
|
|
{
|
|
return new BMessage (B_SIMPLE_DATA);
|
|
}
|
|
|
|
int
|
|
be_add_message_data (void *message, const char *name,
|
|
int32 type_code, const void *buf,
|
|
ssize_t buf_size)
|
|
{
|
|
BMessage *msg = (BMessage *) message;
|
|
|
|
return msg->AddData (name, type_code, buf, buf_size) != B_OK;
|
|
}
|