This makes getting a pseudoterminal pair a little bit more portable.
Note that grantpt() and unlockpt() are currently no-ops, since we've
already granted the pseudoterminal slave to the calling user.
We also accept O_CLOEXEC to posix_openpt(), unlike some systems. :^)
sys$waitid() takes an explicit description of whether it's waiting for a single
process with the given PID, all of the children, a group, etc., and returns its
info as a siginfo_t.
It also doesn't automatically imply WEXITED, which clears up the confusion in
the kernel.
I've been wanting to do this for a long time. It's time we start being
consistent about how this stuff works.
The new convention is:
- "LibFoo" is a userspace library that provides the "Foo" namespace.
That's it :^) This was pretty tedious to convert and I didn't even
start on LibGUI yet. But it's coming up next.
Previously, `fopen()` didn't contain an implementation for the
append modes, even though the Kernel supports it via `O_APPEND`.
This patch rectifies that by implementing them so an assert is
no longer thrown.
There are some headers in libc that require us to have definitions,
such as `FILE` available to us (such as in `pwd.h`). It is bad
practice to include the entirety of `stdio.h`, so it makes more
sense to put `FILE` into it's own header.
Unparented GActions are still parented to the application like before,
making them globally available.
This makes it possible to have actions that work whenever a specific
window is active, no matter which widget is currently focused. :^)
We should only execute the filename verbatim if it contains a slash (/)
character somewhere. Otherwise, we need to look through the entries in
the PATH environment variable.
This fixes an issue where you could easily "override" system programs
by placing them in a directory you control, and then waiting for
someone to come there and run e.g "ls" :^)
Test: LibC/exec-should-not-search-current-directory.cpp
This is a complete reimplementation of CArgsParser with a different API.
Now, CArgsParser properly supports and distinguishes between:
* Positional arguments (required or not)
* Options
Options can be short and/or long.
The API allows you to add custom option and argument types. A few types are
pre-implemented for convenience:
* Boolean options (take no value)
* String and integer options (take a required value)
* String and integer arguments
* Vector-of-string arguments
This commit doesn't include changes for all the users of CArgsParser (see next
commit for that).
If a DNS server responds with multiple answers for a question, we will
get a newline-separated sequence of answers from LookupServer.
However, we don't handle this properly yet in LibC, so just split the
response by line and only care about the first answer for now.
We should rename all of these functions to match the real VT100 names.
This will make it 100% easier to work on LibVT.
For reference: https://vt100.net/docs/vt100-ug/
The curious "stomp" state occurs when you type your way all the way
over to the right side of the terminal buffer, and we "stomp" once on
the very last column, before jumping to the next line.
We should never go into "stomp" state in response to programmatically
setting the cursor position. This fixes a small artifact in vttest.
To allow for more asynchronous teardown of IClientConnection, make the
post_message() function simply return if called after the IPC socket
has been closed.
This changes copyright holder to myself for the source code files that I've
created or have (almost) completely rewritten. Not included are the files
that were significantly changed by others even though it was me who originally
created them (think HtmlView), or the many other files I've contributed code to.
Previously it was created the first time you requested a context menu
for the GTextEditor by right-clicking in it.
That meant it wasn't possible to use Ctrl+L to "go to line" before you
had first right-clicked the editor.
It's useful for the GTextDocument to have access to the initiating
GTextEditor widget during the initial execution of a command.
Since commands are executed via calls to GUndoCommand::redo(), we do
this by wrapping the invocation of redo() in a new helper called
GTextDocumentUndoCommand::execute_from(GTextDocument::Client).
This is then used to fetch the current auto-indentation feature state
and the soft tab width, both used by text insertion.
Now that String::split() defaults to keep_empty=false, we need to make
sure the pwd and grp functions in LibC keep the empty ones.
This fixes "id" moaning about invalid lines in /etc/group.
GModel subclasses can now override drag_data_type() to specify which type
GAbstractView should set for drag data. The default implementation returns a
null string, which disables dragging from this widget.
It's now an abstract (pure virtual) public method in GAbstractView that
individual widgets have to implement. This will allow us to move more
selection-related logic into GAbstractView in order to share it between
implementations.
The "stay_within" parameter to CObject::dispatch_event() optionally
specifies a node in the CObject parent chain where event dispatch
should stop bubbling upwards.
Since event dispatch is done recursively, this was not working right,
as we would simply return from the innermost dispatch loop, leaving
the event un-accepted, which meant that the penultimately inner
dispatch loop would pick up the event and keep bubbling it anyway.
This made it possible for events to jump across window boundaries
within an application, in cases where one window was a CObject ancestor
of another window. This is typically the case with dialog windows.
Fix#1078.
A process has one of three veil states:
- None: unveil() has never been called.
- Dropped: unveil() has been called, and can be called again.
- Locked: unveil() has been called, and cannot be called again.
Sergey suggested that having a non-zero O_RDONLY would make some things
less confusing, and it seems like he's right about that.
We can now easily check read/write permissions separately instead of
dancing around with the bits.
This patch also fixes unveil() validation for O_RDWR which previously
forgot to check for "r" permission.
This syscall is a complement to pledge() and adds the same sort of
incremental relinquishing of capabilities for filesystem access.
The first call to unveil() will "drop a veil" on the process, and from
now on, only unveiled parts of the filesystem are visible to it.
Each call to unveil() specifies a path to either a directory or a file
along with permissions for that path. The permissions are a combination
of the following:
- r: Read access (like the "rpath" promise)
- w: Write access (like the "wpath" promise)
- x: Execute access
- c: Create/remove access (like the "cpath" promise)
Attempts to open a path that has not been unveiled with fail with
ENOENT. If the unveiled path lacks sufficient permissions, it will fail
with EACCES.
Like pledge(), subsequent calls to unveil() with the same path can only
remove permissions, not add them.
Once you call unveil(nullptr, nullptr), the veil is locked, and it's no
longer possible to unveil any more paths for the process, ever.
This concept comes from OpenBSD, and their implementation does various
things differently, I'm sure. This is just a first implementation for
SerenityOS, and we'll keep improving on it as we go. :^)
Currently the points of a triangle do not need to be initialised in a
certain orientation. Currently, the only real method in the class is
`contains`. However we can continue extending the class if and when we
need more functionality.
As suggested by Joshua, this commit adds the 2-clause BSD license as a
comment block to the top of every source file.
For the first pass, I've just added myself for simplicity. I encourage
everyone to add themselves as copyright holders of any file they've
added or modified in some significant way. If I've added myself in
error somewhere, feel free to replace it with the appropriate copyright
holder instead.
Going forward, all new source files should include a license header.
I kept on trying to use the enter key to navigate a tree view, when only
left and right arrow keys are used for this. Now also suport the return
key, is used as a toggle to open a tree.
It used to only read the data it could get without blocking. Andreas says this
was intentional, but it's counterintuitive and no code that uses read_all()
actually expects it to return only a part of the data. So change it to always
read data until an EOF (or an error) is received.
The syscall is now called sys$open(), but it behaves like the old sys$openat().
In userspace, open_with_path_length() is made a wrapper over openat_with_path_length().
It was possible to craft a custom ELF executable that when symbolicated
would cause the kernel to read from user-controlled addresses anywhere
in memory. You could then fetch this memory via /proc/PID/stack
We fix this by making ELFImage hand out StringView rather than raw
const char* for symbol names. In case a symbol offset is outside the
ELF image, you get a null StringView. :^)
Test: Kernel/elf-symbolication-kernel-read-exploit.cpp
When the new font is a different size, just use that font for bold
glyphs as well. It would be nice to find a matching bold version of
the new font automatically in the future.
Add "Link", "ActiveLink" and "VisitedLink" colors to the system theme
definition, and implement support for them in LibHTML.
Note that <body link="foo" alink="bar" vlink="baz"> takes precedence
over the system colors. Author style also takes precedence, since we
only fetch the system color in case the CSS color is -libhtml-link.
CArgsParser::parse_next_param did not properly ensure that, when
a param required a following argument, there were enough parameters left to
complete the parse. This meant that params_left could become negative,
avoiding parse_next_param's termination condition, and cause a segfault
when reading from argv with an out of bounds index.
This fixes the check to ensure that we do in fact have the right amount
of parameters and also adds an assertion to ensure that params_left does
not become negative.
These will make sure there's no funny business or funny offsets in the
main ELF header or each Program Header. More can still be done (like
validating section headers), but this is a good start
Since a chroot is in many ways similar to a separate root mount, we can also
apply mount flags to it as if it was an actual mount. These flags will apply
whenever the chrooted process accesses its root directory, but not when other
processes access this same directory for the outside. Since it's common to
chdir("/") immediately after chrooting (so that files accessed through the
current directory inherit the same mount flags), this effectively allows one to
apply additional limitations to a process confined inside a chroot.
To this effect, sys$chroot() gains a mount_flags argument (exposed as
chroot_with_mount_flags() in userspace) which can be set to all the same values
as the flags argument for sys$mount(), and additionally to -1 to keep the flags
set for that file system. Note that passing 0 as mount_flags will unset any
flags that may have been set for the file system, not keep them.
This patch adds a new replace widget that cooperates with the find
widget, the replace widget takes the input in the find textbox, searches
for occurences of that input, and replaces them with the input provied
in the replace textbox.
This patch implements basic support for OpenBSD-style pledge().
pledge() allows programs to incrementally reduce their set of allowed
syscalls, which are divided into categories that each make up a subset
of POSIX functionality.
If a process violates one of its pledged promises by attempting to call
a syscall that it previously said it wouldn't call, the process is
immediately terminated with an uncatchable SIGABRT.
This is by no means complete, and we'll need to add more checks in
various places to ensure that promises are being kept.
But it is pretty cool! :^)
We now support these mount flags:
* MS_NODEV: disallow opening any devices from this file system
* MS_NOEXEC: disallow executing any executables from this file system
* MS_NOSUID: ignore set-user-id bits on executables from this file system
The fourth flag, MS_BIND, is defined, but currently ignored.
O_EXEC is mentioned by POSIX, so let's have it. Currently, it is only used
inside the kernel to ensure the process has the right permissions when opening
an executable.
At the moment, the actual flags are ignored, but we correctly propagate them all
the way from the original mount() syscall to each custody that resides on the
mounted FS.
Other implementations of pthread_setname_np() do not take the name
length as an argument.
For pthread_getname_np(), other implementations take the buffer size
as a size_t.
This patch brings us in line with other implementations.
While I was updating syscalls to stop passing null-terminated strings,
I added some helpful struct types:
- StringArgument { const char*; size_t; }
- ImmutableBuffer<Data, Size> { const Data*; Size; }
- MutableBuffer<Data, Size> { Data*; Size; }
The Process class has some convenience functions for validating and
optionally extracting the contents from these structs:
- get_syscall_path_argument(StringArgument)
- validate_and_copy_string_from_user(StringArgument)
- validate(ImmutableBuffer)
- validate(MutableBuffer)
There's still so much code around this and I'm wondering if we should
generate most of it instead. Possible nice little project.
The chroot() syscall now allows the superuser to isolate a process into
a specific subtree of the filesystem. This is not strictly permanent,
as it is also possible for a superuser to break *out* of a chroot, but
it is a useful mechanism for isolating unprivileged processes.
The VFS now uses the current process's root_directory() as the root for
path resolution purposes. The root directory is stored as an uncached
Custody in the Process object.
Note that I'm developing some helper types in the Syscall namespace as
I go here. Once I settle on some nice types, I will convert all the
other syscalls to use them as well.
This is a shiny new widget that can display a tree using Miller columns ^:)
In many cases, the columns view can be used as an alternative to tree view,
but it has its own set of limitations:
* It can only display one model column (so it cannot replace a table)
* It takes up a lot of horizontal space, so it's only suitable if the item text
is fairly short
* It can only display one subtree at a time
But as long as a usecase doesn't suffer from these limitations, a columns view
can be *much* more intuitive than a tree view.
We used to have two different models for displaying file system contents:
the FileManager-grade table-like directory model, which exposed rich data
(such as file icons with integrated image previews) about contents of a
single directory, and the tree-like GFileSystemModel, which only exposed
a tree of file names with very basic info about them.
This commit unifies the two. The new GFileSystemModel can be used both as a
tree-like and as a table-like model, or in fact in both ways simultaneously.
It exposes rich data about a file system subtree rooted at the given root.
The users of the two previous models are all ported to use this new model.
The userspace execve() wrapper now measures all the strings and puts
them in a neat and tidy structure on the stack.
This way we know exactly how much to copy in the kernel, and we don't
have to use the SMAP-violating validate_read_str(). :^)
When loading a new executable, we now map the ELF image in kernel-only
memory and parse it there. Then we use copy_to_user() when initializing
writable regions with data from the executable.
Note that the exec() syscall still disables SMAP protection and will
require additional work. This patch only affects kernel-originated
process spawns.
Since ELFDynamicObject needs the actual virtual address of the .dynamic
section in the loaded image, and not the file offset like we assumed
before, due to MAP_PRIVATE secretly giving us a MAP_SHARED, we can
remove all of the Dynamic* code from ELFImage.
ELFDynamicLoader only needs ELFImage to get the Program headers at this
point. More consolidation opportunities seem likely in the future.
We need to workaround the fact that MAP_PRIVATE when passed a file
descriptor doesn't work the way we expect. We can't change the
permissions on our mmap to PROT_WRITE if the original executable doesn't
have PROT_WRITE.
Because of this, we need to construct our ELFDynamicObject using the
actual virtual address of the .dynamic section, instead of using the
offset into the ELFImage that was actually getting modified by accident
...somehow. Not clear what was going on.
We were not recomputing the internal dimensions after a font changed,
which caused things to look very off.
It's still not perfect as we're always using the same (small) font for
bold text, which obviously sticks out like a sore pinky when the rest
of the terminal text is large.
Previously if more than one item was selected clicking on one of
them and dragging would de-select everything that is not the one that
was clicked on. Now, if more than one items are selected and there
is a mousedown it goes into a "mightdrag" state.
The user can then perform a drag, if they don't everything that is not
the item being clicked gets unselected in the mouseup event, mimicking
the previous behavior.
Before this, you could make the kernel copy memory from anywhere by
setting up an ELF executable with a program header specifying file
offsets outside the file.
Since ELFImage didn't even know how large it was, we had no clue that
we were copying things from outside the ELF.
Fix this by adding a size field to ELFImage and validating program
header ranges before memcpy()'ing to them.
The ELF code is definitely going to need more validation and checking.
If we pass a null path to these syscall wrappers, just return EFAULT
directly from the wrapper instead of segfaulting by calling strlen().
This is a compromise, since we now have to pass the path length to the
kernel, so we can't rely on the kernel to tell us that the path is at
a bad memory address.
I though it would be nice to also show the style that the browser uses
to display an element.
In order to do that, in place of the styles table I've put a tab widget,
with tabs for both element and computed element styles.
LibHTML will now use the palette colors for the default document background and
the text. As always, a page can override this default styling with CSS if it
really wants a specific color or style.
Fixes https://github.com/SerenityOS/serenity/issues/963
Previously we would consider anything in the large padded area around
each item to also be part of the item for mouse event purposes.
This didn't feel right when rubberbanding, so this patch factors out
the per-item rect computation into a get_item_rects() helper which can
then be used by the various functions that need it.
Separate some responsibilities:
ELFDynamicLoader is responsible for loading elf binaries from disk and
performing relocations, calling init functions, and eventually calling
finalizer functions.
ELFDynamicObject is a helper class to parse the .dynamic section of an
elf binary, or the table of Elf32_Dyn entries at the _DYNAMIC symbol.
ELFDynamicObject now owns the helper classes for Relocations, Symbols,
Sections and the like that ELFDynamicLoader will use to perform
relocations and symbol lookup.
Because these new helpers are constructed from offsets into the .dynamic
section within the loaded .data section of the binary, we don't need the
ELFImage for nearly as much of the loading processes as we did before.
Therefore we can remove most of the extra DynamicXXX classes and just
keep the one that lets us find the location of _DYNAMIC in the new ELF.
And finally, since we changed the name of the class that dlopen/dlsym
care about, we need to compile/link and use the new ELFDynamicLoader
class in LibC.
This fixes an issue in SystemMonitor where old data would linger in the
table views after selecting a process owned by another user.
Since we can no longer read /proc/PID/* unless PID belongs to us,
we will now present empty views for these processes. :^)
When selecting an element in the browser's DOM inspector, we now also
show the resolved CSS properties (and their values) for that element.
Since the inspector was growing a bit more complex, I moved it out of
the "show inspector" action callback and into its own class.
In the future, we will probably want to migrate the inspector down to
LibHTML to make it accessible to other clients of the library, but for
now we can keep working on it inside Browser. :^)
This code never worked, as was never used for anything. We can build
a much better SHM implementation on top of TmpFS or similar when we
get to the point when we need one.
For dynamic loading, the symbol bind of a symbol actually doesn't
matter. We could do what old glibc did and try to find a strong
symbol for any weak definitions, but the ELF spec doesn't require
it and they changed that a few years ago anyway. So, moot point. :)
We were not sending the ID of the window that was listening for window
management (WM) events along with the WM messages. They only included
the "target" window's ID.
Since the taskbar's single window had the first window ID for its own
connection to the WindowServer, it meant that it would only receive
WM events for the first window ID in other processes as well.
This broke when I ported WindowServer to LibIPC.
Fix this by including the WM listener ID in all WM messages, and since
we're here anyway, get rid of a bunch of unnecessary indirection where
we were passing WM events through the WindowServer event loop before
sending them to the listener.
ELFDynamicObject::load looks a lot better with all the steps
re-organized into helpers.
Add plt_trampoline.S to handle PLT fixups for lazy loading.
Add the needed trampoline-trampolines in ELFDynamicObject to get to
the proper relocations and to return the symbol back to the assembly
method to call into from the PLT once we return back to user code.
We weren't calling the method here before because it was ill-formed.
No start files meant that we got the front half of the init section but
not the back half (no 'ret' in _init!). Now that we have the proper
crtbeginS and crtendS files from libgcc to help us out, we can assume
that DSOs will have the proper _init method defined.
The scrollbar width must be factored in, and one too many
m_line_spacing were being factored into the height. These caused an
initial terminal opening in 80x25 to get resized right away and
shrunk down to 77x24.
This patch also adds some missing relocation defines to exec_elf.h,
and a few helper classes/methods to ELFImage so that we can use it
for our dynamically loaded libs and not just main program images from
the kernel :)
This patch introduces a syscall:
int set_thread_boost(int tid, int amount)
You can use this to add a permanent boost value to the effective thread
priority of any thread with your UID (or any thread in the system if
you are the superuser.)
This is quite crude, but opens up some interesting opportunities. :^)
Threads now have numeric priorities with a base priority in the 1-99
range.
Whenever a runnable thread is *not* scheduled, its effective priority
is incremented by 1. This is tracked in Thread::m_extra_priority.
The effective priority of a thread is m_priority + m_extra_priority.
When a runnable thread *is* scheduled, its m_extra_priority is reset to
zero and the effective priority returns to base.
This means that lower-priority threads will always eventually get
scheduled to run, once its effective priority becomes high enough to
exceed the base priority of threads "above" it.
The previous values for ThreadPriority (Low, Normal and High) are now
replaced as follows:
Low -> 10
Normal -> 30
High -> 50
In other words, it will take 20 ticks for a "Low" priority thread to
get to "Normal" effective priority, and another 20 to reach "High".
This is not perfect, and I've used some quite naive data structures,
but I think the mechanism will allow us to build various new and
interesting optimizations, and we can figure out better data structures
later on. :^)
This removes a bunch of JsonValue copying from the hot path in thread
statistics fetching.
Also pre-size the thread statistics vector since we know the final size
up front. :^)
Instead of using ByteBuffer (which always malloc() their storage) for
IPC message encoding, we now use a Vector<u8, 1024>, which means that
messages smaller than 1 KB avoid heap allocation entirely.
The widget layout system currently works by having layouts size the
children of a widgets. The children then get resize events, giving them
a chance to lay out their own children, etc.
In keeping with this, we need to handle the resize event before calling
do_layout() in a widget, since the resize event handler may do things
that end up affecting the layout, but layout should not affect the
resize event since the event comes from the widget parent, not itself.
LibCore timers now have a TimerShouldFireWhenNotVisible flag which is
set to "No" by default.
If "No", the timer will not be fired by the event loop if it's within
a CObject tree whose nearest GWindow ancestor is currently not visible
for timer purposes. (Specificially, this means that the window is
either minimized or fully occluded, and so does not want to fire timers
just to update the UI.)
This is another nice step towards a calm and serene operating system.
This is memory that's loaded from an inode (file) but not modified in
memory, so still identical to what's on disk. This kind of memory can
be freed and reloaded transparently from disk if needed.
Dirty private memory is all memory in non-inode-backed mappings that's
process-private, meaning it's not shared with any other process.
This patch exposes that number via SystemMonitor, giving us an idea of
how much memory each process is responsible for all on its own.
Palette is now a value wrapper around a NonnullRefPtr<PaletteImpl>.
A new function, set_color(ColorRole, Color) implements a simple
copy-on-write mechanism so that we're sharing the PaletteImpl in the
common case, but allowing you to create custom palettes if you like,
by getting a GWidget's palette, modifying it, and then assigning the
modified palette to the widget via GWidget::set_palette().
Use this to make PaintBrush show its palette colors once again.
Fixes#943.
Lock each directory before entering it so when using -j, the same
dependency isn't built more than once at a time.
This doesn't get full -j parallelism though, since one make child
will be sitting idle waiting for flock to receive its lock and
continue making (which should then do nothing since it will have
been built already). Unfortunately there's not much that can be
done to fix that since it can't proceed until its dependency is
built by another make process.
When filling in some missing part of a window (typically happens during
interactive window resize) we now use the ColorRole::Background from
the system theme palette instead of expecting the clients to send us
the same information when creating windows.
WindowServer now tracks whether windows are occluded (meaning that
they are completely covered by one or more opaque windows sitting above
them.) This state is communicated to the windows via WindowStateChanged
messages, which then allow GWindow to mark its backing store volatile.
This reduces the effective memory impact of windows that are not at all
visible to the user. Very cool. :^)
Compiling LibCore on macOS is needed if one wants to compile host tools (like IPCCompiler) on a non Linux host. These changes could be possibly reverted once "event loop" functionality and "base library" (Vector, String etc.) will be split in two separate libraries,
updating all relevant projects.
This functon will draw an ellipse which is intersecting the corners of
the rect given. It is a very naive implementation, taking 200 samples of
points around the ellipse, and drawing straight lines between each of
these points.
The ellipses look good enough to me though!
WindowServer will now send out a WindowStateChanged message to clients
when one of their windows is minimized.
This is then forwarded to the GWindow, which will try to mark its
underlying window backing store as volatile.
This allows the kernel to steal the memory used by minimized windows
in case it starts running low. Very cool! :^)
This patch implements a simple version of the futex (fast userspace
mutex) API in the kernel and uses it to make the pthread_cond_t API's
block instead of busily sched_yield().
An arbitrary userspace address is passed to the kernel as a "token"
that identifies the futex and you can then FUTEX_WAIT and FUTEX_WAKE
that specific userspace address.
FUTEX_WAIT corresponds to pthread_cond_wait() and FUTEX_WAKE is used
for pthread_cond_signal() and pthread_cond_broadcast().
I'm pretty sure I'm missing something in this implementation, but it's
hopefully okay for a start. :^)
Make sure we always line up the "hole" in the progress bar with the
right side of the paint rect. This fixes a 1px wide glitch seen when
using a darker system theme.
Instead of directly manipulating LDFLAGS, set LIB_DEPS in each
subdirectory Makefile listing the libraries needed for
building/linking such as "LIB_DEPS = Core GUI Draw IPC Core".
This adds each library as an -L and -l argument in LDFLAGS, but
also adds the library.a file as a link dependency on the current
$(PROGRAM). This causes the given library to be (re)built before
linking the current $(PROGRAM), but will also re-link any binaries
depending on that library when it is modified, when running make
from the root directory.
Also turn generator tools like IPCCompiler into dependencies on the
files they generate, so they are built on-demand when a particular
directory needs them.
This all allows the root Makefile to just list directories and not
care about the order, as all of the dependency tracking will figure
it out.
GApplication now has a palette. This palette contains all the system
theme colors by default, and is inherited by a new top-level GWidget.
New child widgets inherit their parents palette.
It is possible to override the GApplication palette, and the palette
of any GWidget.
The Palette object contains a bunch of colors, each corresponding to
a ColorRole. Each role has a convenience getter as well.
Each GWidget now has a background_role() and foreground_role(), which
are then looked up in their current palette when painting. This means
that you no longer alter the background color of a widget by setting
it directly, rather you alter either its background role, or the
widget's palette.
Color themes are loaded from .ini files in /res/themes/
The theme can be switched from the "Themes" section in the system menu.
The basic mechanism is that WindowServer broadcasts a SharedBuffer with
all of the color values of the current theme. Clients receive this with
the response to their initial WindowServer::Greet handshake.
When the theme is changed, WindowServer tells everyone by sending out
an UpdateSystemTheme message with a new SharedBuffer to use.
This does feel somewhat bloated somehow, but I'm sure we can iterate on
it over time and improve things.
To get one of the theme colors, use the Color(SystemColor) constructor:
painter.fill_rect(rect, SystemColor::HoverHighlight);
Some things don't work 100% right without a reboot. Specifically, when
constructing a GWidget, it will set its own background and foreground
colors based on the current SystemColor::Window and SystemColor::Text.
The widget is then stuck with these values, and they don't update on
system theme change, only on app restart.
All in all though, this is pretty cool. Merry Christmas! :^)
We were casting the pthread_mutex_t* instead of pthread_mutex_t::lock
to an Atomic<u32>. This still worked fine, since "lock" is the first
member of pthread_mutex_t.
This is a bit sad, but, with the Allocators as static globals their
destructors were running before some user code. Which doesn't really
make much sense, as none of the members of (at least the basic one) do
any real heavy lifting or have many resources to RAII.
To avoid the problem, just mmap the memory for the global arrays of
Allocators in __malloc_init and let the Kernel collect the memory when
we're done with the process.
These guys are all declared as globals, and their ASSERT_NOT_REACHED
in the destructor doesn't play nice with __cxa_atexit. As in, every
application will assert in __cxa_finalize if this assert isn't removed.
Implement __cxa_atexit and __cxa_finalize per the Itanium spec,
and convert stdlib's atexit and exit() to to call them instead of
a custom 'C-only' atexit implementation.
We always want to put crt0.o in the location where it can get picked
up by the i686-pc-serenity toolchain.
This feels a bit hackish but should get the build working again. :^)
Use simple stack cookies to try to provoke an assertion failure on
stack overflow.
This is far from perfect, since we use a constant cookie instead of
generating a random one on startup, but it can still help us catch
bugs, which is the primary concern right now. :^)
Allow everything to be built from the top level directory with just
'make', cleaned with 'make clean', and installed with 'make
install'. Also support these in any particular subdirectory.
Specifying 'make VERBOSE=1' will print each ld/g++/etc. command as
it runs.
Kernel and early host tools (IPCCompiler, etc.) are built as
object.host.o so that they don't conflict with other things built
with the cross-compiler.
These fields are intended to carry the real meat of a drag operation,
and the "text" is just for what we show on screen (alongside the cursor
during the actual drag.)
The data field is just a String for now, but in the future we should
make it something more flexible.
Now that Frame knows the visible viewport rect, it can easily ignore
repaint requests from e.g <blink> elements that are not currently
scrolled into view. :^)
When the visible viewport rect changes, we walk the layout tree and
check where each LayoutImage is in relation to the viewport rect.
Images outside have their bitmaps marked as volatile.
Note that the bitmaps are managed by ImageDecoder objects. If a bitmap
is purged by the kernel while volatile, we construct a new ImageDecoder
next time we need pixels for the image.
A client that only ever does synchronous IPC calls from its side would
never actually process incoming asynchronous messages since they would
arrive while waiting for a synchronous response and then end up sitting
forever in the "unhandled messages" queue.
We now always handle unhandled messages using a deferred invocation.
This fixes the bug where Audio.MenuApplet didn't learn that the muted
state changed in response to its own request to change it. :^)
Instead of implementing menu applets as their own thing, they are now
WSWindows of WSWindowType::MenuApplet.
This makes it much easier to work with them on the client side, since
you can just create a GWindow with the right type and you're in the
menubar doing applet stuff :^)
This patch adds a single "kernel info page" that is mappable read-only
by any process and contains the current time of day.
This is then used to implement a version of gettimeofday() that doesn't
have to make a syscall.
To protect against race condition issues, the info page also has a
serial number which is incremented whenever the kernel updates the
contents of the page. Make sure to verify that the serial number is the
same before and after reading the information you want from the page.
Currently only Ext2FS and TmpFS supports InodeWatchers. We now fail
with ENOTSUPP if watch_file() is called on e.g ProcFS.
This fixes an issue with FileManager chewing up all the CPU when /proc
was opened. Watchers don't keep the watched Inode open, and when they
close, the watcher FD will EOF.
Since nothing else kept /proc open in FileManager, the watchers created
for it would EOF immediately, causing a refresh over and over.
Fixes#879.
This logic is all taken care of by GAbstractColumnView now, so we can
simply delete GTreeView::context_menu_event(). :^)
Fixes an issue mentioned in #826
4KB gets pretty mmap/munmap heavy when downloading larger files,
so bump this a bit to reduce time spent in memory allocation.
This can be improved in various ways, but I'm not sure what the
best way forward is at the moment.
This makes GTreeView able to support multi-column models!
Only one column can be the "tree column", this is column 0 by default
but can be changed by overriding GModel::tree_column().
When the filesystem model is updated, it is rebuilt. This means dangling
indexes inside the TreeView metadata table will have old information and random
directories will toggle open. Clearing the table alleviates this issue.
The kernel now supports basic profiling of all the threads in a process
by calling profiling_enable(pid_t). You finish the profiling by calling
profiling_disable(pid_t).
This all works by recording thread stacks when the timer interrupt
fires and the current thread is in a process being profiled.
Note that symbolication is deferred until profiling_disable() to avoid
adding more noise than necessary to the profile.
A simple "/bin/profile" command is included here that can be used to
start/stop profiling like so:
$ profile 10 on
... wait ...
$ profile 10 off
After a profile has been recorded, it can be fetched in /proc/profile
There are various limits (or "bugs") on this mechanism at the moment:
- Only one process can be profiled at a time.
- We allocate 8MB for the samples, if you use more space, things will
not work, and probably break a bit.
- Things will probably fall apart if the profiled process dies during
profiling, or while extracing /proc/profile
When a GAction is activated by a menu, or by a toolbar button, you can
now use GAction::activator() to get a pointer to whomever activated it.
This can be used to implement context-specific behaviors in situations
where the same action is exposed through multiple paths.
This addresses an issue that was brought up in #826.
We now take advantage of SharedBuffers being purgeable memory by
setting the volatile flag on window back buffers while not painting
into them.
This means that one of the two backing stores used by each window
is purgeable+volatile most of the time, allowing the kernel to purge
it to recover memory if needed.
Note that this is only relevant when double-buffering is turned on,
but since that is the default, this does affect most apps. :^)