Instead of doing a forced layout synchronously whenever an element's
style is changed, use a zero-timer to do the forced relayout on next
event loop iteration.
This effectively coalesces a lot of layouts and makes many pages such
as GitHub spend way less time doing redundant layout work.
Previously the client would only learn the mime type of what was being
dropped on it once the drop occurred. To enable more sophisticated
filtering of drag & drop, we now pass along the list of mime types being
dragged to the client with each MouseMove event.
(Note that MouseMove is translated to the various Drag* events in LibGUI
on the client side.)
If a widget accept()'s a "drag enter" event, that widget now becomes
the application-wide "pending drop" widget. That state is cleared if
the drag moves over another widget (or leaves the window entirely.)
We were using the "accept" flag on the event to break out of the
bubbling loop, but this had lasting consequences since all events that
bubbled too far came out looking as if someone had accepted them.
If an event is ignored by everyone, it should appear ignored.
These events allow widgets to react when a drag enters/leaves their
rectangle. The enter event carries position + mime type, while the
leave event has no information.
AT_SECURE is set in the auxiliary vector when we execute setuid/setgid
programs.
In those cases, we do not want to read environment variables that
influence the logic of the dynamic loader, as they can be controlled
by the user.
Previously, when trying to parse the location info of a member
variable, we asserted that the location info of its parent is of type
'Address'.
However, there are cases where we cannot compute the location info of
the parent (for example - because we do not yet support the type of
debug info generated for it).
In those cases, it is better to just leave the location info of the
member variable empty instead of crashing.
DebugSession now makes the loader stop after loading the libraries,
and parses the loaded libraries of the program before continuing its
execution.
DebugSession now also supports inserting a breakpoint at a given symbol
or source position.
Additionally, DebugInfo now takes the base address of its object into
consideration.
If set, the dynamic loader will perform a software breakpoint after
loading all libraries, and just before jumping to the main entry point.
This allows a debugger to inspect the loaded libraries before the
program starts executing.
This patch implements the "remove irrelevant boxes" and "generate
missing child wrappers" parts of table fixup.
"Generate missing parents" is left as a task for our future selves.
It seems like both BFC and IFC can have absolutely positioned children.
It's a bit strange, but consider the following HTML:
<html><body>foobar<img style="position: absolute"></body></html>
In such a document, the <img> element is an absolutely positioned child
of a block-level element (<body>) with no block-level children.
An IFC is established for <body>, and needs to handle layout for <img>.
Various whitespace-related issues have been fixed, and support for the
different CSS white-space values is improved enough that I think we can
stop doing the hack where we just prune whitespace nodes from the tree
and actually let them show up.
This is a nice step forward for correctness with the slight downside of
cluttering up layout tree dumps with tons of whitespace text nodes.
But hey, that's the web we know & love. :^)
Fixes#4427.
The StyleResolver can find the specified CSS values for the parent
element via the DOM. Forcing everyone to locate specified values for
their parent was completely unnecessary.
Layout nodes now only carry CSS computer values with them. The main
idea here is to give them only what they need to perform layout, and
leave the rest back in the DOM.
Put all the inherited members in one struct and all the non-inherited
ones in another.
This makes it clear which is which, and also makes it easy to copy all
the inherited values while ignoring the non-inherited ones.
Another step towards not having to carry the full specified style with
us everywhere. This isn't the ideal final layout, since we're mixing
computed and used values a bit randomly here, but one step at a time.
We shouldn't reject indexed palette PNGs just because they have fewer
palette entries than the bit depth allows. Instead, we need to check
for OOB palette accesses and fail the decode *then*.
When changing the mouse cursor (e.g when hovering over a link) we now
only change the InProcessWebView's override cursor instead of setting
the cursor at the window level.
This fixes an issue where the I-beam or hand cursors would somehow
"escape" from the web view and over to other widgets.
This patch adds a global (per-process) filter list to LibWeb that is
used to filter all outgoing resource load requests.
Basically we check the URL against a list of filter patterns and if
it's a match for any one of them, we immediately fail the load.
The filter list is a simple text file:
~/.config/BrowserContentFilters.txt
It's one filter per line and they are simple glob filters for now,
with implicit asterisks (*) at the start and end of the line.
Instead of each window having a bool flag that says whether that window
is currently active, have a pointer to the active window on the app
object instead.
When constructing a GlobalObject, it has to pass itself as the global
object to its own Shape. Since this is done in the Object constructor,
and Object is a base class of GlobalObject, it's not yet valid to cast
"this" to a GlobalObject*.
Fix this by having Shape store the global object as an Object& and move
Shape::global_object() to GlobalObject.h where we can at least perform a
valid static_cast in the getter.
Found by oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29267
Just because an inline-block is inline doesn't mean it's ready to
accept random inline children. If it's a block, we may need to create
an anonymous wrapper first.
Fixes#4604.
This patch adds sys$abort() which immediately crashes the process with
SIGABRT. This makes assertion backtraces a lot nicer by removing all
the gunk that otherwise happens between __assertion_failed() and
actually crashing from the SIGABRT.
Having the text cursor disappear during rapid continuous editing is
quite jarring, so let's make sure we always restart the blink cycle
whenever the user performs some kind of editing action in a frame.
This fixes an issue (mainly) with multiline prompts, where a multiline
prompt would overwrite the lines before it when libline tries to display
it.
To reproduce, set `PROMPT="a\nb\nc> "` in the shell, then press return
a few times.
If this flag is enabled for a widget, it will be automatically sized
based on its children. This only works for widgets using a layout.
This allows you to put widgets inside each other without having to
manually calculate how large the container should be. It's not the
perfect API but it's a decent progression in ergonomics. :^)
Because ProcFS will refresh the data upon seek to 0, we can re-use
the same file descriptor. This saves us from having to open it every
time, but it also reduces the odds that we are unable to open a new
file descriptor due to low memory conditions.
This will be useful for both the Playground app as well as for a
standalone CLI tool (à la clang-format). It cannot handle comments yet
(and will drop them from the formatted output), but other than that it
produces valid GML that matches the formatting we have so far! :^)
This patch makes hyperlinked terminal cells require a double click
to activate. The appearance of a hovered link is changed to not look
like a classic underlined link, but instead like some kind of typical
double-clickable GUI widget.
Also the hover cursor for links is changed from Hand to Arrow.
A strong symbol anywhere in an executable must override any
weak symbol used in any library. This means that the weak symbol
must be overridden by a strong symbol even if the strong symbol
is in a dependent library. This means we need to perform relocations
twice, and resolve weak symbols globally before attempting to resolve
them locally. Consequentially we need to defer performing any
initialisations until after we have performed the second round of
relocations.
Loader.so now just performs the initial self relocations and static
LibC initialisation before handing over to ELF::DynamicLinker::linker_main
to handle the rest of the process.
As a trade-off, ELF::DynamicLinker needs to be explicitly excluded from
Lagom unless we really want to try writing a cross platform dynamic loader
Clients of LaunchServer can now provide a list of allowed handlers,
optionally with a specific set of URLs. The list can be sealed to
prevent future additions to it.
If LaunchServer receives a request to open something not on the allowed
handlers list, it will disconnect the client immediately.
The main idea here is to allow otherwise restricted programs to launch
specific things, e.g "Help" to open their manual, or "Browser" to load
the SerenityOS home page. :^)
This gets a lot of unecessary includes out of Widget.cpp. Doing this
didn't work before, but improvements in the C library and using dynamic
libraries have likely un-broken it :^).
Also, move the registration global object to an anonymous namespace. No
reason it has to be an extern symbol.
...as well as the few remaining references to set_foreground_color().
These properties are not being used for rendering anymore, presumably
because they completely mess up theming - assigning random white and
gray backgrounds just doesn't work with dark themes.
I've chosen to not replace most of the few remaining uses of this
broken functionality with custom palette colors (the closest
replacement is background_role) for now (except for Minesweeper where
squares with mines are painted red again now), as no one has actually
complained about them being broken, so it must look somewhat decent
(some just look right anyway). :^)
Examples of this are the taskbar buttons, which apparently had a
DarkGray foreground color for minimized windows once - this has since
been replaced with bold/regular font. Another one is the Profiler's
ProfileTimelineWidget, which is supposed to have a white background -
which it didn't have for quite some time, it's grey now (with the
default theme, that is). Doesn't look bad either.
We were jumping through some pretty wasteful hoops in the resize event
handler of OOPWV by first creating a bitmap and then immediately
creating a new (shareable) clone of that bitmap. Now we go straight
to the shareable bitmap instead.
Previously we had a static stack check cookie value for LibC.
Now we randomize the cookie value on LibC initialization, this should
help make the stack check more difficult to attack (still possible just
a bigger pain). This should also help to catch more bugs.
This aims to be a "smart" autocomplete that tries to present the user
with useful suggestions without being in the way (too much).
Here is its current configuration:
- Show suggestions 800ms after something is inserted in the editor
- if something else is inserted in that period, reset it back to 800ms
to allow the user to type uninterrupted
- cancel any shown autocomplete (and the timer) on external changes
(paste, cut, etc)
Modify the user mode runtime to insert stack canaries to find stack corruptions.
The `-fstack-protector-strong` variant was chosen because it catches more
issues than vanilla `-fstack-protector`, but doesn't have substantial
performance impact like `-fstack-protector-all`.
Details:
-fstack-protector enables stack protection for vulnerable functions that contain:
* A character array larger than 8 bytes.
* An 8-bit integer array larger than 8 bytes.
* A call to alloca() with either a variable size or a constant size bigger than 8 bytes.
-fstack-protector-strong enables stack protection for vulnerable functions that contain:
* An array of any size and type.
* A call to alloca().
* A local variable that has its address taken.
Example of it catching corrupting in the `stack-smash` test:
```
courage ~ $ ./user/Tests/LibC/stack-smash
[+] Starting the stack smash ...
Error: Stack protector failure, stack smashing detected!
Shell: Job 1 (/usr/Tests/LibC/stack-smash) Aborted
```
Empty boxes should be fully collapsed, but a box with border and/or
padding is not empty.
This fixes an issue where <hr> elements were getting weirdly collapsed
since they have zero content height (but some border height.)
There's no spatial navigation here, Left/Up moves to the previous
sibling in the tab order, while Right/Down moves to the next.
The arrow keys keep focus within the same parent widget, unlike the tab
key which cycles through all focusable widgets in the window.
This makes GUI::MessageBox feel a bit nicer since you can now arrow
between the Yes/No/Cancel buttons. :^)
This brings mmap more in line with other operating systems. Prior to
this, it was impossible to request memory that was definitely committed,
instead MAP_PURGEABLE would provide a region that was not actually
purgeable, but also not fully committed, which meant that using such memory
still could cause crashes when the underlying pages could no longer be
allocated.
This fixes some random crashes in low-memory situations where non-volatile
memory is mapped (e.g. malloc, tls, Gfx::Bitmap, etc) but when a page in
these regions is first accessed, there is insufficient physical memory
available to commit a new page.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
Add a function to destroy any keys that were set on the current thread
using the algorithm from Dr. POSIX's pthread_key_create. Add some
defines to pthread.h for pthread key use, and implement
pthread_key_delete. It has a prototype in pthread.h, but any program
trying to actually use it would be in for a link-time surprise.
Currently, keys are destroyed either via global destructors, with the
s_key_destroyer object, or in exit_thread. exit_thread is invoked by
pthread_exit, and transitively by pthread_create, via the
pthread_create_helper that ensures all threads created with the pthread
API properly clean up for themselves when they exit gracefully.
A future patch might make s_key_destroyer a C++11 thread_local instead,
assuming we get thread_local and thread_local destructors working.
Now that we have RTTI in userspace, we can do away with all this manual
hackery and use dynamic_cast.
We keep the is<T> and downcast<T> helpers since they still provide good
readability improvements. Note that unlike dynamic_cast<T>, downcast<T>
does not fail in a recoverable way, but will assert if the object being
casted is not a T.
When calling set_checked(true) on an exclusive button, we will now
transfer focus to the newly checked button if one of its now-unchecked
siblings had focus before.
This makes windows that place initial focus somewhere in a group of
radio buttons look nicer when they show up, since focus will be on
whichever radio button was pre-checked, which may not be the first one
in the group.
Making an AbstractButton exclusive means that we enforce that only one
of the exclusive buttons within the same parent widget can be checked
at a time.
RadioButton was doing exactly the same thing, except in a custom way.
So just remove the custom code and make it exclusive. :^)
Old font functionality has been moved into BitmapFont
and an abstract Font interface has been introduced to
faciliate further development of TTF font integration.
WavWriter::finalize didn't check that m_file was actually valid before
trying to seek and close it. The file is only set by set_file, so it's
not an invariant. Just add a null guard to finalize().
Because pthread_create will always call pthread_exit internally before
exiting the thread function, we can remove the odd requirement that the
user's thread function must call Thread::quit internally.
Make Thread::join clear m_tid on success, and print to stderr on
failure. Call join from ~Thread(). Now if you write an infinite loop in
your thread in an application and don't have an exit condition, you will
block in the thread's destructor forever. Time for stop_token? :)
Just constructing one of these guys on the stack willy nilly will leak
the first reference to them. There might be other C_OBJECTs that have
public constructors, seems like a good place for some static analysis
checks :).
Force users to call the construct() method for it.
Compared to version 10 this fixes a bunch of formatting issues, mostly
around structs/classes with attributes like [[gnu::packed]], and
incorrect insertion of spaces in parameter types ("T &"/"T &&").
I also removed a bunch of // clang-format off/on and FIXME comments that
are no longer relevant - on the other hand it tried to destroy a couple of
neatly formatted comments, so I had to add some as well.
We don't want to trigger an actual selection change until either
confirming the new selection by keyboard or clicking on it.
Dismissing the dropdown should have no effect on the current
selection.
Fixes#4657
We previously had a cached bold variant font in Gfx::Font that was very
haphazardly located by filename pattern. This patches replaces that
mechanism with a proper Gfx::FontDatabase lookup for the same font but
with bold weight (700).
Since RefPtr<T> decrements the ref counter to 0 and after that starts
destructing the object, there is a window where the ref count is 0
and the weak references have not been revoked.
Also change WeakLink to be able to obtain a strong reference
concurrently and block revoking instead, which should happen a lot
less often.
Fixes a problem observed in #4621
The new algorithm is an iterative one with an arbitrary threshold for splitting
curves. It splits curves evenly. This should theoretically be less accurate
than the existing recursive approach, but seems to give subjectively better
results in practice.
I'm planning to make this a minimal-allocation TTF parser. This will
speed up start-up time for applications, but have some overhead for
rasterizing glyphs. Which should be okay, since rasterized glyph bitmaps
should be cached anyway.
This commit just adds the loading of the HEAD table.
This is a new NotesEntry type which will allow applications to embed
arbitrary metadata in crashdumps (stored as a JSON string). It will be
used to store an assertion message, for example.
This is a new NotesEntry type which contains information related to the
coredump's process:
- PID
- executable path
Having these in the coredump explicitly avoids having to parse them from
the coredump filename and backtrace, respectively.
This patchset makes ProtocolServer stream the downloads to its client
(LibProtocol), and as such changes the download API; a possible
download lifecycle could be as such:
notation = client->server:'>', server->client:'<', pipe activity:'*'
```
> StartDownload(GET, url, headers, {})
< Response(0, fd 8)
* {data, 1024b}
< HeadersBecameAvailable(0, response_headers, 200)
< DownloadProgress(0, 4K, 1024)
* {data, 1024b}
* {data, 1024b}
< DownloadProgress(0, 4K, 2048)
* {data, 1024b}
< DownloadProgress(0, 4K, 1024)
< DownloadFinished(0, true, 4K)
```
Since managing the received file descriptor is a pain, LibProtocol
implements `Download::stream_into(OutputStream)`, which can be used to
stream the download into any given output stream (be it a file, or
memory, or writing stuff with a delay, etc.).
Also, as some of the users of this API require all the downloaded data
upfront, LibProtocol also implements `set_should_buffer_all_input()`,
which causes the download instance to buffer all the data until the
download is complete, and to call the `on_buffered_download_finish`
hook.
Instead of hard-coding 22 in random places, just make the following
widgets have a fixed height of 22 by default: Button, CheckBox,
ColorInput, ComboBox, RadioButton, SpinBox, TextBox.
In the future we can make this relative to the current font size,
but for now at least this centralizes the setting a bit better.
This patch removes size policies and preferred sizes, and replaces them
with min-size and max-size for each widget.
Box layout now works in 3 passes:
1) Set all items (widgets/spacers) to their min-size
2) Distribute remaining space evenly, respecting max-size
3) Place widgets one after the other, adding spacing in between
I've also added convenience helpers for setting a fixed size (which is
the same as setting min-size and max-size to the same value.)
This significantly reduces the verbosity of widget layout and makes GML
a bit more pleasant to write, too. :^)
Fixed sizes are really just shorthands for setting min and max size to
the same value.
This makes it much nicer to express fixed sizes in GML:
Before:
@GUI::Widget {
horizontal_size_policy: "Fixed"
preferred_width: 20
}
After:
@GUI::Widget {
fixed_width: 20
}
This patch adds min_size and max_size properties to GUI::Widget. These
can also be accessed as min_width/min_height and max_width/max_height.
Layouts will respect these constraints and size widgets accordingly.
This fixes 4 issues:
- RECONSUME_IN_RETURN_STATE was functionally equivalent to
SWITCH_TO_RETURN_STATE, which caused us to lose characters.
For example, &test= would lose the =
- & characters by themselves would be lost. For example, 1 & 2
would become 1 2. This is because we forgot to flush
characters in the the ANYTHING_ELSE path in CharacterReference
- Named character references didn't work at all in attributes.
This is because there was a path that was checking the entity
code points instead of the entity itself. Plus, the path that
was checking the entity itself wasn't quite spec compliant.
- If we fail to match a named character reference, the first
character is lost. For example &test would become &est.
However, this relies on a little hack since I can't wrap my
head around on how to change the code to do as the spec says.
The hack is to reconsume in AmbigiousAmpersand instead of
just switching to it.
Fixes#3957
Such errors are raised when SyntaxError nodes are executed, and are also
used for internal control flow.
The 'break' and 'continue' commands are currently only allowed inside
for loops, and outside function bodies.
This also adds a 'loop' keyword for infinite loops.
Creating a backtrace from a crashdump already existed as a few
standalone functions in CrashDaemon. This patch refactors the code
required for this to make it generally usable and moves it to
CoreDump::Backtrace, which provides both raw data as well as
stringification.
This makes it possible to construct a read-only (or display-only)
TextEditor in GML:
@GUI::TextEditor {
mode: "ReadOnly"
text: "Well hello friends! :^)"
}
This can be used to register a property that maps enum values to certain
strings, e.g.
REGISTER_ENUM_PROPERTY(
property_name, getter, setter, Enum,
{ Enum::Foo, "Foo" },
{ Enum::Bar, "Bar" });
Also use it for REGISTER_SIZE_POLICY_PROPERTY :^)
As mentioned in 2d39da5 the usual pattern is that LibFoo provides a Foo
namespace - LibCoreDump doesn't, so this renames CoreDumpReader to
Reader and puts it in the CoreDump namespace. :^)
We now map most shared library text segments shared, read+exec only.
This reduces our memory footprint at system startup by 16 MB which is
pretty neat! :^)
We were painting unfinished pixels while waiting for the WebContent
process to render the page. This caused OOPWV to flicker black
sometimes, which looked pretty bad.
This way we still flicker, but at least we flicker with the correct
palette color. :^)
This was causing WindowServer and Taskbar to crash sometimes when the
stars aligned and we tried cutting off a string ending with "..." right
on top of an emoji. :^)
It always felt a bit jarring that tooltips would pop in right away when
you hover over a toolbar button. This patch adds a 700ms delay before
they appear, and a 50ms delay before they disappear.
Once a tooltip is up, moving the cursor between two widgets that both
have tooltips will leave the tooltip on screen without delays.
None of the code using this actually expected the timer to fire right
away, but they would instead call start() on it once they were ready to
accept a timer fire.
Let's make the API behave the way its clients believed it did. :^)
There are three possible selection modes for a GUI::AbstractView.
- NoSelection
- SingleSelection
- MultiSelection
We don't enforce these modes fully yet, this patch mostly adds them in
place of the old "multi select" flag.
Now that fonts know their own weight, we no longer need highlighters to
tell us which font to use. Instead, they can just say "this should be
bold" and we'll find the right font ourselves.
This is mostly based on TextDocument's similar methods, these will
help implement searching within the terminal application.
The support for unicode code points is shaky at best, and should
probably be improved further.
This was mentioned in #4574, and the more I think about it the more it
feels just right - let's move it there! :^)
Having to link LaunchServer against LibGUI explicitly should've been
telling enough...
clang trunk with -std=c++20 doesn't seem to properly look for an
aggregate initializer here when the type being constructed is a simple
aggregate (e.g. `struct Thing { int a; int b; };`). This template fails
to compile in a usage added 12/16/2020 in `AK/Trie.h`.
Both forms of initialization are supposed to call the
aggregate-initializers but direct-list-initialization delegating to
aggregate initializers is a new addition in c++20 that might not be
implemented yet.
This changes the signatures for FILE::seek and FILE::tell, to use
`off_t` as they use lseek internally. `fpos_t` is also redefined to use
`off_t`.
Dr. POSIX says that fpos_t is:
> A non-array type containing all information needed to specify uniquely
> every position within a file.
In practice, most *NIX typedef it to `off_t`, or a struct containing an
`off_t` and some internal state.
This way, if you press F2 to edit the name of an item, the name will be
selected in the editor that pops up, and you can start typing a new
name for it immediately.
Move the shadow 1 more pixel away from the unhovered icon location,
making a total 2 pixel distance between the icon and the shadow.
Also tweak the shadow color to be a darkened variant of the base color
underneath the icon.