Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rcore] Clipboard Image Support #4459

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open

Conversation

evertonse
Copy link
Contributor

@evertonse evertonse commented Nov 1, 2024

[rcore] Clipboard Image

Overview

I've implemented a small start for Clipboard Image functionality for raylib. The implementation is only for desktop Windows OS and it's only GetClipboardImage. I want to implement SetClipboardImage, but I need to know a few things first regarding whether my approach is proper for the project.

2024-11-01.15-47-40.mp4

You'll see I created rcore_clipboard_win32 that implements this from scracth using winapi.
We can question "Why not use already implemented clipboard functions from platform abstractions such as GLFW, SDL, and RGFW and adpated to our needs?" Because they either did not implement it, or it is only available on the bleeding edge (SDL3).

  • From what I've seen, SDL has clipboard image support but only since SDL 3.1.3 SDL_clipboard.h from SDL3. In that case, I check for the major and minor version and implement using SDL functions; otherwise, it just returns NULL (I could add a warning or implement using rcore_clipboard_win32). Also, SDL3 has a migration section, so I'm not even sure that the current raylib SDL platform is suited for SDL3. Just to double-check, there's no SDL_GetClipboardData in SDL2 SDL_clipboard.h from SDL2.

  • RGFW only supports clipboard Unicode text from what I could see: RGFW.h - Line 643.

  • GLFW is still in the process of implementing clipboard image functionality: GLFW Pull Request #2385.

How it is structured

In this PR, works like this: if we detect that the platform is either GLFW or RGFW and we're on Windows, then we include rcore_clipboard_win32.c. The file rcore_clipboard_win32.c went the route of defining windgi.h structs that are needed, taking care of any name collisions.

Takeaway

What I'm thinking is that when clipboard image manipulation becomes a stable feature for GLFW, we can easily add it to rcore_desktop_glfw. But for platforms that don't support it (such as SDL2, RGFW, and current GLFW) we could have "utils" platform functions such as GetClipboardImage (next would be SetClipboardImage) implemented seperatly such as in this PR.

Concerns

Another thing to add is that now it couples rcore and rtexture by the Image struct and the LoadImageFromMemory function. Furthermore, it is required to have SUPPORT_FILEFORMAT_BMP enabled.

Finally, the whole implementation is behind the flag SUPPORT_CLIPBOARD_IMAGE, which in this branch I've enabled by default in config.h.

I've added core_clipboard_image example to make it easy to check it out (it doesn't have to be permanent, also it hasn't updated its related files besides the examples Makefile)

This is kind of a draft. Sorry for the wall of text, I just tought it was important to share this to aid your decision and allow further development.

Update comment

@evertonse evertonse marked this pull request as draft November 1, 2024 19:40
@raysan5
Copy link
Owner

raysan5 commented Nov 3, 2024

@evertonse This is an amazing addition! Thanks for working on it! About the best way to address this addition, it should be addressed by every supported rcore backend platform in a different way:

  • RGFW: I think it could be directly added to RGFW.h library, probably its creator @ColleagueRiley can help on that.
  • SDL: Functionality is already provided by the library so it can be directly supported by rcore_desktop_sdl backend, as already implemented.
  • GLFW: This is the most tricky backend at the moment because despite there is an open PR on the base library it could take a lot of time to be merged. I'd prefer to avoid the current approach of implementing it in rcore_clipboard_win32.c, maybe it can be directly implemented in rcore_desktop_glfw.c? Another option could be rglfw.c module or move it to a separate external/win32_clipboard.c library.

Please, let me know your thoughts!

@ColleagueRiley
Copy link
Contributor

@evertonse I'll look into this for RGFW ASAP 👍

@evertonse
Copy link
Contributor Author

evertonse commented Nov 7, 2024

Update

I've worked on the desktop platforms much in the way it was suggested.

TLDR

Created an SDL3 layer to enable GetClipboardImage functionality , with the bonus that it works on Linux with SDL3. Additionally, for GLFW and RGFW, it was created a separate file, ./external/win32_clipboard.h to be used by both platforms.

SDL

To support clipboard images on the SDL platform, we need SDL3.
As I've suspected, the current implementation for rcore_platform_sdl is not compatible with SDL3.
To allow compilation with both versions (SDL2 and SDL3), it was created a compatibility layer following the SDL3 Migration Guide. Now it's possible to compile with both SDL2 or SDL3.

I have successfully ported the functionality as far as I could test, allowing GetClipboardImage function to work on Wayland Ubuntu, as shown below:

Untitled.video.-.Made.with.Clipchamp.1.mp4

Another benefit of adding SDL3 support is that some raylib functions that were previously unsupported on that platform are now available, such as GetWindowScaleDPI.

With SDL3, we now check for additional MIME types. I noticed that on Wayland Ubuntu, the clipboard saves images as PNG, so we now check for the following MIME types:

  • image/bmp
  • image/png
  • image/jpg
  • image/tiff

Compilation

Also I have modified the src/Makefile and examples/Makefile to enable compilation for SDL3.

After building and installing SDL3 on /usr/local, I was able to compile raylib and all examples with the following command (on Linux):

make PLATFORM=PLATFORM_DESKTOP_SDL  \
SDL_INCLUDE_PATH=/usr/local/include/SDL3/ \
SDL_LIBRARY_PATH=/usr/local/lib SDL_LIBRARIES=-lSDL3
export LD_LIBRARY_PATH=/usr/local/lib # libSDL3.so is located here

On MinGW, I used the following command to compile on Windows.
Consider SDL3 installed on ```~/.local/": we now need EXTRA_INCLUDE_PATHS because of the include style in SDL3.h (`<SDL3/file.h>`) as opposed to SDL2.h ("file.h"):

make PLATFORM=PLATFORM_DESKTOP_SDL  \
SDL_INCLUDE_PATH="$HOME/.local/include/SDL3/" EXTRA_INCLUDE_PATHS="-I$HOME/.local/include/"  \
SDL_LIBRARY_PATH=$HOME/.local/lib SDL_LIBRARIES=-lSDL3

We need to be aware that when compiling raylib with SDL3 on Windows, there is currently a chance of getting corrupted bitmaps from the clipboard in SDL3 version 3.1.6. I've opened a PR about this issue, and it has been added as a milestone for SDL 3.2.

It might be important to say that compiling SDL3 statically with raylib create's name colision now, because of these Matrix functions. It's still possible do compile statically if we use objcopy --redefine-sym on libSDL3.a

RGFW & GLFW

I followed your advice and created a header-only library in ./src/external/ for Windows only, which I used for the RGFW and GLFW platforms. As soon as both libraries implement this functionality we can roll back and implement GetClipboardImage in terms of those platforms.

Finally

If this approach is proper, I can continue working on the SetClipboardImage function. I consider this PR now ready for further review.

Quick example to test it

#include "raylib.h"

int main(int argc, char *argv[])
{
    InitWindow(800, 450, "[core] raylib clipboard image");
    SetTraceLogLevel(LOG_TRACE);
    SetTargetFPS(60);

    Image img = {0};
    Texture tex = {0};
    while(!WindowShouldClose())
    {
        if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V))
        {
            img = GetClipboardImage();
            tex = LoadTextureFromImage(img);
            if(!IsTextureValid(tex))
            {
                TraceLog(LOG_WARNING, "Could not get clipboard image");
            }
        }

        BeginDrawing();
            ClearBackground(RAYWHITE);
            if (IsTextureValid(tex))
            {
                DrawTexture(tex, 0, 10 + 21, WHITE);
            }
            DrawText("Print Screen and Crtl+V", 10, 10, 21, BLACK);
        EndDrawing();
    }
}

@evertonse evertonse marked this pull request as ready for review November 7, 2024 03:33
@evertonse evertonse changed the title [rcore] Draft: Clipboard Image Support [rcore] Clipboard Image Support Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants