BEdit»Blog

Trip to history lane and Linux update - soon

DISCLAMER This post contains information about Windows and Linux, and it might appear that I think one is better than the other. Let's be perfectly honest, they're both bad just in different ways. Please avoid propaganda / dogmatic comments, flame wars are bad for the blood pressure.

------------

Long long time ago when I started entering my first C keywords for the compiler to complain about, I used Knoppix (before that I was happy in Delphi and good ol' QBasic with Windows ME and earlier). But I never really got into C or the OS proper back then, only when I switched back to Windows and Mingw environment I started to really learn C, and due to the '++', also C++. As the experience grew, a need to communicate to the OS directly was required and I started to learn how to talk to "Windows.h". Easy, just go to MSDN and find the right API call!

As BEdit port to Linux has been on-going, I've been sadly surprised how tricky some things are to implement that are just a little bit tricky on Windows.

Let's take a very poorly communicated feature of the BEdit GUI, drag and drop as an example.

If you drag a file (or more) on top of the GUI window, if will open the file as a layout file if the file extension is .bet, else it will open it as a binary file. The code that handles the drop logic on windows looks somewhat like this (in a pseudo-codeish language):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// In the window message callback switch
    case WM_DROPFILES:
        UINT fileCount = windows_getAmountOfFilesDropped();
        for (UINT i = 0; i < fileCount; ++i)
        {
            UINT filenameLength = windows_getFilenameLength(i);
            void* buffer = alloc(filenameLength);
            windows_loadFilename(i, buffer);
            utf8_string path = convertToUTF8(buffer);
            app_PushDropFile(path);
        }
        windows_doneWithDrop();
        break;


In practice, from windows I need
1. to intercept the callback
2. API call to get amount of files
3. API call to get buffer size I need to allocate for filename
4. API call to get filename
5. API call to tell I'm done, clean everything up on your side

For a more complete reference I'm using the DrawQueryFileW and DragFinish calls, there are newer API calls I could use to get notified when a file is being hovered on the window (and where), but that is for later iterations.

The entire platform related code to handle the drop is 27 lines (I didn't even bother putting it as a separate file). Easy to get up and running, easy to use. I'm not sure how much code newer Windows API calls to do the same would be, probably a non-insignificant amount.

Now to port that to Linux...

Well, a concept of a "window" is not really native to Linux. To utilize windowed applications you talk to X11. Of course X11, being very old and at that time "drag and drop" wasn't really a thing, doesn't have native support for it either. X11 is (as far as my limited knowledge goes) utilizing network sockets to communicate between applications. So it's only natural that drag and drop support is using a network pattern, you send requests and get responses you then again reply to. (BTW, this also goes for clipboard support, you ask the application controlling the clipboard and get a response with the content.) This has been standardized as XDND - Drag-and-Drop Protocol for the X Window System.

So how does one implement drag and drop support on Linux? Well, you can do it the easy way - grab a library that does it (like GTK or QT) - or you can do it the hard way, read the specs and implement it. I picked the hard way because I like to make my own bugs rather than inheriting other's. The steps are fairly straight forward:
1. Setup the communication (i.e. set up the protocol request constants / atoms).
2. Decide what version of the protocol to use (ah yea, there are 5 versions of XDND).
3. Set property of your window to allow drag and drop so other processes know to communicate to you.
4. Listen to drop start event.
5. Investigate what the possible formats (using MIME) of what is being hovered over you are.
6. Communicate back that you're interested in what is being dropped, what purpose you're going to use the data for and in what area you accept the drops in.
7. Listen to drop end, in case it dropped on your window
8. Request the data.
9. Wait for response.
10. Parse the data using MIME type (in case of drag and drop files it's text/uri-list)

In the case of BEdit, this translates to over 500 lines of code, about 20x of the Window's version.

As drag and drop support is done, and also non-english keyboard support - the only major feature left is OS font support (I'm assuming Linux has OS fonts), after that a Linux build of the GUI will be available.
Benjamin Pedersen,
Sounds annoying. Cool that Linux support is getting close, though. I know some Linux users that might be interested in BEdit.