This change unfortunately cannot be atomically made without a single
commit changing everything.
Most of the important changes are in LibIPC/Connection.cpp,
LibIPC/ServerConnection.cpp and LibCore/LocalServer.cpp.
The notable changes are:
- IPCCompiler now generates the decode and decode_message functions such
that they take a Core::Stream::LocalSocket instead of the socket fd.
- IPC::Decoder now uses the receive_fd method of LocalSocket instead of
doing system calls directly on the fd.
- IPC::ConnectionBase and related classes now use the Stream API
functions.
- IPC::ServerConnection no longer constructs the socket itself; instead,
a convenience macro, IPC_CLIENT_CONNECTION, is used in place of
C_OBJECT and will generate a static try_create factory function for
the ServerConnection subclass. The subclass is now responsible for
passing the socket constructed in this function to its
ServerConnection base; the socket is passed as the first argument to
the constructor (as a NonnullOwnPtr<Core::Stream::LocalServer>) before
any other arguments.
- The functionality regarding taking over sockets from SystemServer has
been moved to LibIPC/SystemServerTakeover.cpp. The Core::LocalSocket
implementation of this functionality hasn't been deleted due to my
intention of removing this class in the near future and to reduce
noise on this (already quite noisy) PR.
Using a WeakPtr to keep a reference to the active layer caused it to
be destroyed when the last tab was closed, which made the
m_layer == layer check in set_layer() return early since it was
already null. Because of this the LayerPropertiesWidget was never
disabled.
After closing the last open ImageEditor, selecting a color would try to
dereference it causing a crash. Instead make set_image_editor() take a
pointer to it and set it to nullptr when closing the last tab like we
do with LayerListWidget and LayerPropertiesWidget.
Now, each new filter only has to describe how to actually change
the bitmaps, and the common logic of pulling out the bitmap from the
layer, and marking the action as done, etc is all handled in the
`Filter` base class.
This also makes it possible to apply filters to external bitmaps,
which are not embedded in a `Layer` (which we can use to preview
filters in the future!)
Previously, we would clear it if there was still an editor open. This
was not obvious because it was only visible when an inactive tab was
closed, since closing an active tab would trigger an editor change
which would re-fill the layers widget.
This allows us to request any specific editor to close itself. Earlier,
this could only be done for the currently active editor, so trying to
close inactive tabs would not work properly.
Previously the save logic was hardcoded to only work for the active
editor, so closing editors in the background would not properly
handle the unsaved changes. This patch brings us closer to be able
to fix that problem.
The rotate clockwise/rotate counterclockwise actions can be added to
CommonActions since they are repeated in FontEditor, ImageViewer and
PixelPaint. This keeps the shortcuts and icons consistent across
applications.
This is just a slight variation of `/res/icons/16x16/paste.png`, I've
removed the lines on the paper to make it look consistent with the
"New Image" icon, which is an empty piece of paper.
I think this is likely the more common operation and makes more sense
in the toolbar. It calls the 'save as' action internally anyway if there
is no associated file.
Now, when trying to close the application, there is a separate prompt
for each open tab with unsaved changes. Each tab is closed after it is
handled appropriately (assuming the user didn't Cancel), this makes it
so that the message box is always asking about the currently active tab,
allowing the user to see that the image contains.
If at any point the user presses "Cancel", all remaining tabs are kept
open.
Previously MainWidget::request_close() would always put up the
message box asking to save unsaved changes, even if there aren't any.
This patch makes it so that the message box is only shown if the
undo stack is in a modified state.
As noted in the latest hacking video, it doesn't seem to make much
sense to store the title and path in the image itself. These fields
have now been moved to the actual ImageEditor itself.
This allows some nice simplicfications, including getting rid of the
`image_did_change_title` hook of ImageClient (which was just a way to
report back to the editor that the title had changed).
A bloom filter creates fringes around bright areas in the image
mimicking the behavior of real-world cameras.
It gets its own category "Artistic" in the Filter Gallery since its not
one filter per se but a combination of multiple.
The filter works as follows:
- Get only the light areas (above a threshold) of the image
- Blur that image
- Compose onto the original image
The FastBoxBlurFilter has been living in LibGfx for a while and now
it's accessible in PixelPaint. The parameters for the filter are exposed
via the new Filter Gallery.
The wrong conception that done() would stop the program flow right there
lead to the lambda not properly aborting when no filter was selected.
The ExecAborted would be processed and then the nullptr that was
m_selected_filter would be happily dereferenced.
This patch fixes that.
Now, the filters can supply the Filter Gallery with a GUI::Widget such
that the user can interact with the filter. The Filter Gallery in turn
only calls apply() on the filter once it should be run.
This decouples the PixelPaint filters a lot from the ones supported by
LibGfx and paves the way to filters with settings.
For now there still are just the plain LibGfx filters so this change
feels like introducing a lot of boilerplate, but in the future there
will be a lot more to see.
This patch adds the bare bones of the new Filter Gallery.
For now, only the gml and the basic layout got added, a fairly boringw
indow pops up when "Filter Gallery" is called.
The code for the Model used by the TreeView is taken in large parts from
HackStudio's VariableModel.
Keep a RefPtr to offset_text_box in EditGuideDialog instead of using
a local pointer. Previously the lambda in ok_button.on_click() would
outlive the local variable causing a crash.
With this change, System::foo() becomes Core::System::foo().
Since LibCore builds on other systems than SerenityOS, we now have to
make sure that wrappers work with just a standard C library underneath.