Skip to content

Commit

Permalink
Fixes for the windows code in clipboard api
Browse files Browse the repository at this point in the history
  • Loading branch information
HazardousPeach committed Oct 14, 2024
1 parent f722dd3 commit dd129ca
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 108 deletions.
193 changes: 96 additions & 97 deletions src/gui/clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,96 +54,6 @@ namespace Toolbox {
return types;
}

Result<std::string, ClipboardError> SystemClipboard::getText() const {
if (!OpenClipboard(nullptr)) {
return make_clipboard_error<std::string>("Failed to open the clipboard!");
}

HANDLE clipboard_data = GetClipboardData(CF_TEXT);
if (!clipboard_data) {
return make_clipboard_error<std::string>("Failed to retrieve the data handle!");
}

const char *text_data = static_cast<const char *>(GlobalLock(clipboard_data));
if (!text_data) {
return make_clipboard_error<std::string>(
"Failed to retrieve the buffer from the handle!");
}

std::string result = text_data;

if (!GlobalUnlock(clipboard_data)) {
return make_clipboard_error<std::string>("Failed to unlock the data handle!");
}

if (!CloseClipboard()) {
return make_clipboard_error<std::string>("Failed to close the clipboard!");
}

return result;
}
// Assume the clipboard contains file paths and return them in a
// vector. Returns a clipboardError if the clipboard doesn't have
// files in it.
Result<std::vector<fs_path>, ClipboardError> SystemClipboard::getFiles() const {
// Get the file list target.
auto data = getContentType("text/uri-list");
// If the clipboard doesn't have a file list, propogate the
// error.
if (!data) {
return std::unexpected<ClipboardError>(data.error());
}
auto lines = data.value().get_urls();
// Allocate a vector of paths, and convert the vector of
// strings to it. When doing so, strip off the "file://"
// prefix.
std::vector<fs_path> result((int)lines.size());
for (int i = 0; i < lines.size(); ++i) {
if (line.starts_with("file:/")) {
if (src_path_str.starts_with("file:///")) {
result[i] = src_path_str.substr(8);
} else {
result[i] = src_path_str.substr(7);
}
} else {
return make_clipboard_error<std::vector<fs_path>>("Can't copy non file uri");
}
}
return result;
}

Result<void, ClipboardError> SystemClipboard::setText(const std::string &text) {
if (!OpenClipboard(nullptr)) {
return make_clipboard_error<void>("Failed to open the clipboard!");
}

if (!EmptyClipboard()) {
return make_clipboard_error<void>("Failed to clear the clipboard!");
}

HANDLE data_handle = GlobalAlloc(GMEM_DDESHARE, text.size() + 1);
if (!data_handle) {
return make_clipboard_error<void>("Failed to alloc new data handle!");
}

char *data_buffer = static_cast<char *>(GlobalLock(data_handle));
if (!data_buffer) {
return make_clipboard_error<void>("Failed to retrieve the buffer from the handle!");
}

strncpy_s(data_buffer, text.size() + 1, text.c_str(), text.size() + 1);

if (!GlobalUnlock(data_handle)) {
return make_clipboard_error<void>("Failed to unlock the data handle!");
}

SetClipboardData(CF_TEXT, data_handle);

if (!CloseClipboard()) {
return make_clipboard_error<void>("Failed to close the clipboard!");
}
return {};
}

Result<MimeData, ClipboardError>
getContentType(std::unordered_map<std::string, UINT> &mime_to_format,

Check failure on line 59 in src/gui/clipboard.cpp

View workflow job for this annotation

GitHub Actions / build (Windows Build, windows-latest, x64, windows, /*)

'getContentType': modifiers not allowed on nonmember functions
Expand Down Expand Up @@ -197,15 +107,13 @@ namespace Toolbox {
if (format == CF_HDROP) {
HDROP hdrop = static_cast<HDROP>(data_handle);
UINT num_files = DragQueryFile(hdrop, 0xFFFFFFFF, nullptr, 0);
std::string uri_list;
std::vector<std::string> uri_list;
uri_list.reserve(num_files);
for (UINT i = 0; i < num_files; ++i) {
UINT size = DragQueryFile(hdrop, i, nullptr, 0);
std::string file(size, '\0');
DragQueryFile(hdrop, i, file.data(), size + 1);
uri_list += std::format("file:///{}", file);
if (i != num_files - 1) {
uri_list += "\r\n";
}
uri_list.push_back(file);
}

if (!GlobalUnlock(clipboard_data)) {
Expand Down Expand Up @@ -240,7 +148,98 @@ namespace Toolbox {

return make_clipboard_error<MimeData>("Unimplemented MIME type!");
}
Result<MimeData, ClipboardError> SystemClipboard::getContent(const std::string &type) const {
Result<std::string, ClipboardError> SystemClipboard::getText() const {
if (!OpenClipboard(nullptr)) {
return make_clipboard_error<std::string>("Failed to open the clipboard!");
}

HANDLE clipboard_data = GetClipboardData(CF_TEXT);
if (!clipboard_data) {
return make_clipboard_error<std::string>("Failed to retrieve the data handle!");
}

const char *text_data = static_cast<const char *>(GlobalLock(clipboard_data));
if (!text_data) {
return make_clipboard_error<std::string>(
"Failed to retrieve the buffer from the handle!");
}

std::string result = text_data;

if (!GlobalUnlock(clipboard_data)) {
return make_clipboard_error<std::string>("Failed to unlock the data handle!");
}

if (!CloseClipboard()) {
return make_clipboard_error<std::string>("Failed to close the clipboard!");
}

return result;
}
// Assume the clipboard contains file paths and return them in a
// vector. Returns a clipboardError if the clipboard doesn't have
// files in it.
Result<std::vector<fs_path>, ClipboardError> SystemClipboard::getFiles() const {
// Get the file list target.
auto data = getContentType(m_mime_to_format, "text/uri-list");
// If the clipboard doesn't have a file list, propogate the
// error.
if (!data) {
return std::unexpected<ClipboardError>(data.error());
}
auto lines = data.value().get_urls().value();
// Allocate a vector of paths, and convert the vector of
// strings to it. When doing so, strip off the "file://"
// prefix.
std::vector<fs_path> result;
result.reserve((int)lines.size());
for (auto &line : lines) {
if (line.starts_with("file:/")) {
if (line.starts_with("file:///")) {
result.push_back(line.substr(8));
} else {
result.push_back(line.substr(7));
}
} else {
return make_clipboard_error<std::vector<fs_path>>("Can't copy non file uri");
}
}
return result;
}

Result<void, ClipboardError> SystemClipboard::setText(const std::string &text) {
if (!OpenClipboard(nullptr)) {
return make_clipboard_error<void>("Failed to open the clipboard!");
}

if (!EmptyClipboard()) {
return make_clipboard_error<void>("Failed to clear the clipboard!");
}

HANDLE data_handle = GlobalAlloc(GMEM_DDESHARE, text.size() + 1);
if (!data_handle) {
return make_clipboard_error<void>("Failed to alloc new data handle!");
}

char *data_buffer = static_cast<char *>(GlobalLock(data_handle));
if (!data_buffer) {
return make_clipboard_error<void>("Failed to retrieve the buffer from the handle!");
}

strncpy_s(data_buffer, text.size() + 1, text.c_str(), text.size() + 1);

if (!GlobalUnlock(data_handle)) {
return make_clipboard_error<void>("Failed to unlock the data handle!");
}

SetClipboardData(CF_TEXT, data_handle);

if (!CloseClipboard()) {
return make_clipboard_error<void>("Failed to close the clipboard!");
}
return {};
}
Result<MimeData, ClipboardError> SystemClipboard::getContent() const {
// Figure out all possible formats the content can be in.
auto formats = getAvailableContentFormats();
// If that didn't work, propogate the error.
Expand All @@ -251,7 +250,7 @@ namespace Toolbox {
MimeData result;
for (std::string &target : formats.value()) {
// Get the target of each type.
auto data = getContenttype(target, m_mime_to_format);
auto data = getContentType(m_mime_to_format, target);
if (!data) {
return std::unexpected<ClipboardError>(data.error());
}
Expand Down
21 changes: 11 additions & 10 deletions src/gui/dragdrop/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,17 @@ namespace Toolbox::UI {
}
}

std::string uri_paths;
std::vector<std::string> uri_paths;

HDROP hdrop = (HDROP)GlobalLock(stg_medium.hGlobal);

if (hdrop) {
UINT num_files = DragQueryFile(hdrop, 0xFFFFFFFF, nullptr, 0);
uri_paths.reserve(num_files);
for (UINT i = 0; i < num_files; ++i) {
TCHAR file_path[MAX_PATH];
if (UINT length = DragQueryFile(hdrop, i, file_path, MAX_PATH)) {
uri_paths +=
std::format("file:///{}\n", std::string(file_path, length));
uri_paths.push_back(std::string(file_path, length));
}
}
}
Expand Down Expand Up @@ -250,14 +250,15 @@ namespace Toolbox::UI {
DragDropManager::instance().setSystemAction(false);

action->setRender([action](const ImVec2 &pos, const ImVec2 &size) {
std::string urls = action->getPayload().get_urls().value_or("");
if (urls.empty()) {
auto maybe_urls = action->getPayload().get_urls();
if (!maybe_urls) {
return;
}
std::vector<std::string> urls = maybe_urls.value();

ImGuiStyle &style = ImGui::GetStyle();

size_t num_files = std::count(urls.begin(), urls.end(), '\n');
size_t num_files = urls.size();
std::string file_count = std::format("{}", num_files);
ImVec2 text_size = ImGui::CalcTextSize(file_count.c_str());

Expand Down Expand Up @@ -313,12 +314,12 @@ namespace Toolbox::UI {
action = DragDropManager::instance().createDragAction(0, std::move(mime_data));

action->setRender([action](const ImVec2 &pos, const ImVec2 &size) {
std::string urls = action->getPayload().get_urls().value_or("");
if (urls.empty()) {
auto maybe_urls = action->getPayload().get_urls();
if (!maybe_urls) {
return;
}

size_t num_files = std::count(urls.begin(), urls.end(), '\n');
size_t num_files = maybe_urls.value().size();

ImDrawList *draw_list = ImGui::GetBackgroundDrawList();
ImVec2 center = pos + (size / 2.0f);
Expand Down Expand Up @@ -477,4 +478,4 @@ namespace Toolbox::UI {

#endif

} // namespace Toolbox::UI
} // namespace Toolbox::UI
2 changes: 1 addition & 1 deletion src/gui/project/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ namespace Toolbox::UI {

std::vector<std::string> paths;
for (const ModelIndex &index : m_selected_indices) {
paths.push_back(m_file_system_model->getPath(index));
paths.push_back(m_file_system_model->getPath(index).string());
}

result.set_urls(paths);
Expand Down

0 comments on commit dd129ca

Please sign in to comment.