(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)
Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.
We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
Also, only mark the menu bar item as opened if a menu was actually
opened through the menu bar.
These changes allow a menu to be used both in the menu bar as well
as a context menu.
Fixes#5469
A window repaint may change the alpha value, resulting in a different
hit test outcome. In those cases, re-evaluate the cursor hit testing
after a window was painted, and update the cursor if needed.
We didn't add buttons for certain window types or states when the
window was created, but when a window with a button changed its
state to where we would not have created the button, we didn't
remove the existing button.
Tool windows are secondary windows with a smaller title bar. The sit on
the layer above normal windows, and cannot be minimized.
These are intended for complex yet non-modal interactions with the
content of a primary window, such as find/replace windows, property
windows, etc.
Minimum window size can now be customised and set at runtime via the
SetWindowMinimumSize WindowServer message and the set_minimum_size
LibGUI::Window method. The default minimum size remains at 50x50.
Some behind-the-scenes mechanics had to be added to LibGUI::Window to
ensure that the minimum size is remembered if set before the window is
shown. WindowServer sends a resize event to the client if it requests a
size on create that's smaller than it's minimum size.
We need to first deliver the mouse event and possibly the double click
event and record these facts. Then, we need to iterate all global
tracking listeners and deliver the mouse event (but not the double
click event) to any such listener, unless they already had these
events delivered.
Fixes#4703
LookupServer can now itself server as a DNS server! To service DNS clients, it
uses the exact same lookup logic as it does for LibIPC clients. Namely, it will
synthesize records for data from /etc/hosts on its own (you can use this to
configure host names for your domain!), and forward other questions to
configured upstream DNS servers. On top of that, it implements its own caching,
so once a DNS resource record has been obtained from an upstream server,
LookupServer will cache it locally for faster future lookups.
The DNS server part of LookupServer is disabled by default, because it requires
you to run it as root (for it to bind to the port 53) and on boot, and we don't
want either by default. If you want to try it, modify SystemServer.ini like so:
[LookupServer]
Socket=/tmp/portal/lookup
SocketPermissions=666
Priority=low
KeepAlive=1
User=root
BootModes=text,graphical
and enable server mode in LookupServer.ini like so:
[DNS]
Nameservers=...
EnableServer=1
If in the future we implement socket takeover for IP sockets, these limitations
may be lifted.
Where it belongs, alongside the /etc/hosts check. The inner lookup() method is
really about talking to a specific DNS server.
Also, don't bail out on a empty name. An empty DNSName is actually '.' — a
single dot — aka the DNS root.
...just like we store m_lookup_cache, in other words.
This immediately lets us match on types: for instance we will now only resolve
1.0.0.127.in-addr.arpa to localhost if asked for type PTR, not for type A. In
the future, this could also let us have the same /etc/hosts name resolve
to *multiple* addresses.
DNSName can now take care of case conversion when comparing using traits.
It still intentionally doesn't implement operator ==; you have to explicitly
decide whether you want case-sensitive or case-insensitive comparison.
This change makes caches (and /etc/hosts) case-transparent: we will now match
domains if they're the same except for the case.
* DNSName knows how to randomize itself
* DNSPacket no longer constructs DNSQuestion instances, it receives an already
built DNSQuestion and just adds it to the list
* LookupServer::lookup() explicitly calls randomize_case() if it needs to
randomize the case.
This is a wrapper around a string representing a domain name (such as
"example.com"). It never has a trailing dot.
For now, this class doesn't do much except wrap the raw string. Subsequent
commits will add or move more functionality to it.
This wrapper abstracts the watch_file setup and file handling, and
allows using the watch_file events as part of the event loop via the
Core::Notifier class.
Also renames the existing DirectoryWatcher class to BlockingFileWatcher,
and adds support for the Modified mode in this class.
I honestly don't know the internals of all this and what exactly is
going on, but this fixes compositing of the fullscreen window. By trial
and error I found that specifically m_invalidated_all needs to be set to
false, so it's probably different behaviour in prepare_dirty_rects(),
which depends on that...
Either way, the code composing all windows in non-fullscreen mode calls
Window::clear_dirty_rects() for each, so not doing that for the fullscreen
window as well seems like an oversight.
Fixes#4810.
We only cleared the area not covered by the backing bitmap if a
rendering rectangle intersected with the backing bitmap. But because
we are potentially calling the render function many times we need
to always clear the area not covered by the backing bitmap, whether
it intersects or not.
Fixes#5291
Merely moving a window shouldn't require re-rendering the window
frame anymore now that we cache the rendered frame in bitmaps. This
reduces CPU usage significantly when moving windows.
We weren't properly handling switching between having a shadow and
not having a shadow when switching themes. This allows an empty string
in the theme configuration for a shadow path, meaning no shadow should
be rendered.
The WebContent process was redoing page layout every time you scrolled
the page. This was a huge CPU hog for no reason. Fix this by only doing
a relayout when the viewport is resized, not when it moves around.
Button now can handle middle and right clicks.
Added 2 new handlers in button class: on_right_click for Right mouse
button and on_middle_click for middle mouse button.
Added functionality to vertically maximize window with middle mouse
click on the maximize window button.
Also added a way to vertically maximize window by resizing window
height-wise lower than the maximum window height.
Since theme changes may change geometrics, which are also affected by
window shadows, we need to recompute occlusions as well as re-render
window frames.
We only really need to re-render the simple window shadow when
the size of the frame changes. So, for all other cases only re-render
the window frame without rendering the shadow.
This implements simple window shadows around most windows, including
tooltips. Because this method uses a bitmap for the shadow bits,
it is limited to rectangular window frames. For non-rectangular
window frames we'll need to implement a more sophisticated algorithm.
This only renders the window frame once until the size of the window
changes, or some other event requires re-rendering. It is rendered
to a temporary bitmap, and then the top and bottom part is stored
in one bitmap as well as the left and right part. This also adds
an opacity setting, allowing it to be rendered with a different
opacity.
This makes it easier to enhance window themes and allows using
arbitrary bitmaps with e.g. alpha channels for e.g. shadows.
For example, FindInFilesWidget.h mentions GUI::TableView, but did not include
it. On the other hand, all source files that include FindInFilesWidget.h
also include TableView.h, so the issue is only cosmetical.
They're really the same thing: a DNS packet can contain both questions and
answers, and there's a single bit in the header that determines whether the
packet represents a query or a response. It'll be simpler for us to represent
both types of packets using the same class.
This class can be both serialized and deserialized to/from a raw DNS packet.
Now that we no longer depend on the textual IPC format, we can pass IP addresses
in the format most code actually has and needs it: in binary. The only places we
actually have to deal with textual address representation is:
* When reading /etc/hosts, we have to parse textual addresses & convert them to
binary;
* When doing reverse lookups, we have to form a pseudo-hostname of the form
x.x.x.x.in-addr.arpa.
So we do the conversion in those two cases.
This also increases uniformity between how we handle A (IPv4 address) and other
resource record types. Namely, we now store the raw binary data as received from
a DNS server.
The ad-hoc IPC we were doing with LookupServer was kinda gross. With this,
LookupServer is a regular IPC server. In the future, we want to add more APIs
for LookupServer to talk to its clients (such as DHCPClient telling LookupServer
about the DNS server discovered via DHCP, and DNS-SD client browsing for
services), which calls for a more expressive IPC format; this is what LibIPC is
perfect for.
While the LookupServer side is using the regular LibIPC mechanics and patterns,
the LibC side has to hand-roll LibIPC format serialization without actually
using LibIPC. We might be able to get rid of this in the future, but for now it
has to be like that. The good news is the format is not that bad at all.
I originally wanted to batch the symbolication requests but that just
makes the client logic significantly more complicated with no real
benefit other than architectural feelgood points.
The /boot directory is only accessible to root by default, but anyone
wanting access to kernel symbols for development can get them by making
/boot/Kernel accessible to the "symbol" user.
This patch adds SymbolServer, a service daemon that provides
symbolication of ELF binaries. It has a very simple IPC API at the
moment that only turns addresses into symbol names.
This can be used to implement symbolication without having to do
in-process ELF parsing yourself. :^)
The WM_* IPC messages are intended for "outsider" window management,
not for a client's own windows. Make a separate StartWindowResize
message for this.
This was the only reason that every IPC client had to know its server
side client ID.
The PIDs were used for sharing shbufs between processes, but now that
we have migrated to file descriptor passing, we no longer need to know
the PID of the other side.
This patch adds an IPC call for debugging requests. It's stringly typed
and very simple, and allows us to easily implement all the features in
the Browser's Debug menu.
This is a workaround until we can implement a proper <input type=text>
in terms of LibWeb primitives.
This makes google.com not crash in multi-process mode (but there is no
search box.)
We were ignoring everything but A records in DNS responses. This broke
reverse lookups which obviously want the PTR records.
Fix this by filtering on the requested record type instead of always A.
This commit:
- merges the two(!) places that defined independently the minimum size of a window.
- splits Window::normalize_rect(), which was originally just a function to apply
the minimum size requirement, and has taken on the additional job of nudging
windows back onto the desktop.
This inadvertantly fixes a crash that happens when a malicious program creates a
window of size (0, 0). Now, a window at [0,0 50x50] is created instead.
The ImageDecoder service now returns a list of image frames, each with
a duration value.
The code for in-process image decoding is removed from LibWeb, an all
image decode requests are sent out-of-process to ImageDecoder. :^)
This won't scale super well to very long and/or large animations, but
we can work on improving that separately. The main goal here is simply
to stop doing any image decoding inside LibWeb.
Fixes#5165.
This broke in add01b3, where Core::Timer::create_single_shot() was
changed to create a stopped timer. Fix it by actually starting the timer
right away ourselves.
Fixes#5111.
This was done with the help of several scripts, I dump them here to
easily find them later:
awk '/#ifdef/ { print "#cmakedefine01 "$2 }' AK/Debug.h.in
for debug_macro in $(awk '/#ifdef/ { print $2 }' AK/Debug.h.in)
do
find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec sed -i -E 's/#ifdef '$debug_macro'/#if '$debug_macro'/' {} \;
done
# Remember to remove WRAPPER_GERNERATOR_DEBUG from the list.
awk '/#cmake/ { print "set("$2" ON)" }' AK/Debug.h.in
That's what that piece of logic is probably supposed to be doing.
Let's help it acheive that purpose! Apparently the top of the desktop
(i.e. the menubar) was forgotten, so consider it part of the deadzone.
This is based on a comment by @tomuta on #4644, and should prevent all future
instances of bugs like #4644.
Disadvantage: The current implementation may generate a lot of WM_WindowRectChanged
events for a listener while bouncing occurs. Feel free to improve this.
- Unmaximization/untiling had nearly but not quite code duplication;
this patch replaces the actual "regrabbing" logic with Rect::set_size_around.
- When undoing maximization/untiling, it used to be possible to to grab a window
"outside" of its frame, and thus drag it off the screen. This is no longer
possible. Fixes#4644.
- As a side effect, when untiling from the bottom/left/right, the regrab is now
a much smoother experience.
- Setting the resize aspect ratio while being tiled now untiles and umaximizes
the window, as these things are incompatible. Fixes an undocumented bug
(steps to reproduce: maximize, then set aspect ratio).
- When unmaximizing, spurious WindowLeft events were sent, because that path
didn't set hovered_window. Fixes an undocumented bug.
Since these things are interwoven, this is all a single commit.
Previously, SetWindowRect and SetWindowRect could supply basically arbitrary
x and y coordinates. This could happen either due to a malicious or malfunctioning
program, or even due to the auto-centering feature.
This patch also moves the 'normalization' code out of ClientConnection to Window,
where it belongs better.
Fixes#4135.
Fixes#5052.
blit() calls draw_scaled_bitmap() behind the scenes in scaled contexts,
and that doesn't like src_rect to be outside of the source bitmap's
bounds. Implicitly clip with the source rect, like the non-scaled
codepath already does.
Fixes#5017 even more.
Consider
draw_scaled_bitmap({0, 0, 10, 10}, source, {0, 0, 5, 5}).
Imagine wanting to split that up into two calls, like e.g. the
compositor when redrawing the background with damage rects. You really
want to be able to say
draw_scaled_bitmap({0, 0, 5, 10}, source, {0, 0, 2.5, 5})
but up to now you couldn't. Now you can.
This makes painting very low-res images (such as tile.png) in mode
"stretch" work much better.
It's less code, and blit() already handles scaled painters.
Fixes the window server asserting in highdpi mode with a centered
background image. Part of #5017.
draw_scaled_bitmap() has a clearer API (just source and dest rects --
blit_scaled() took those and scale factors and then ignored width and
height on the source rect and it was less clear what it was supposed to
do), and they do mostly the same thing.
The draw_scaled_bitmap() API takes an IntRect as source rect, so it's
currently not always possible to split a big draw_scaled_bitmap() into
two (or more) smaller draw_scaled_bitmap() calls that do the same thing
-- that'd require FloatRects. The compositor kind of wants this to be
possible, but there's already a FIXME about this not looking quite right
with the previous approach either.
draw_scaled_bitmap() handles transparent sources, so after this change
wallpapers with transparency will be blended instead of copied. But that
seems fine, and if not, the Right Fix for that is to remove the alpha
channel from wallpapers after loading them anyways.
As an added bonus, draw_scaled_bitmap() already handles display scale,
so this fixes window server asserts for background images that are shown
as "stretch" (#5017). The window server still asserts for "tile" and
"offset" for now though.
Calling draw_scaled_bitmap() here exposed a bug in it fixed by #5041.
Before that is merged, this change here will cause smearing on the
background image when moving windows around.
Bitmap::load_from_file("foo.png", 2) will now look for "foo-2x.png" and
try load that as a bitmap with scale factor 2 if it exists. If it
doesn't, it falls back to the 1x bitmap as normal.
Only places that know that they'll draw the bitmap to a 2x painter
should pass "2" for the second argument.
Use this new API in WindowServer for loading window buttons and
cursors.
As a testing aid, ctrl-shift-super-i can force HighDPI icons off in
HighDPI mode. Toggling between low-res and high-res icons makes it easy
to see if the high-res version of an icon looks right: It should look
like the low-res version, just less jaggy.
We'll likely have to grow a better API for loading scaled resources, but
for now this suffices.
Things to check:
- `chres 640 480` followed by `chres 640 480 2` followed by
`chres 640 480`
- window buttons in window context menu (in task bar and on title bar)
still have low-res icons
- ctrl-shift-super-i in high-res mode toggles sharpness of window
buttons and of arrow cursorf
- arrow cursor hotspot is still where you'd expect
Gfx::Bitmap can now store its scale factor. Normally it's 1, but
in high dpi mode it can be 2.
If a Bitmap with a scale factor of 2 is blitted to a Painter with
scale factor of 2, the pixels can be copied over without any resampling.
(When blitting a Bitmap with a scale factor of 1 to a Painter with scale
factor of 2, the Bitmap is painted at twice its width and height at
paint time. Blitting a Bitmap with a scale factor of 2 to a Painter with
scale factor 1 is not supported.)
A Bitmap with scale factor of 2 reports the same width() and height() as
one with scale factor 1. That's important because many places in the
codebase use a bitmap's width() and height() to layout Widgets, and all
widget coordinates are in logical coordinates as well, per
Documentation/HighDPI.md.
Bitmap grows physical_width() / physical_height() to access the actual
pixel size. Update a few callers that work with pixels to call this
instead.
Make Painter's constructor take its scale factor from the target bitmap
that's passed in, and update its various blit() methods to handle
blitting a 2x bitmap to a 2x painter. This allows removing some gnarly
code in Compositor. (In return, put some new gnarly code in
LibGfxScaleDemo to preserve behavior there.)
No intended behavior change.
This option was renamed from scaled to stretch in DisplaySettings in
699ba84, but since WindowServer receives a plain string and was not
updated, it wouldn't recognize the new renamed value as a valid option.
Turns out sending plain strings via IPC and only mapping them to enum
values on the receiving end is brittle, we should probably update
Desktop::set_wallpaper_mode() to use an enum as well at some point.
Fixes#5006.
To support this, the GUI process and the WebContent service will now
coordinate their backing store bitmaps. Each backing store can be
referred to by a serial ID, and we don't need to keep resending it
as a file descriptor.
We should probably do something similar in WindowServer. :^)
Now that WindowServer broadcasts the system theme using an anonymous
file, we need clients to pledge "recvfd" so they can receive it.
Some programs keep the "shared_buffer" pledge since it's still used for
a handful of things.
The priority boosting mechanism has been broken for a very long time.
Let's remove it from the codebase and we can bring it back the day
someone feels like implementing it in a working way. :^)
The consolidation of the initialization code between HTTP and HTTPS
downloads was capturing the "job" local by reference, which was not safe
after we left the init() scope.
Fix this by getting the HTTP::Job from the Download object instead.
Whilst SystemMenu maintains a constant WindowServer connection, there
isn't always a Window active on that connection to listen for theme
changes - this causes the current theme in this process to fall out of
sync with the rest of the system. This fixes this problem by
re-requesting an UpdateSystemTheme message when the dialog is
instantiated.
Adds a mechanism through which windowing clients can re-request an
UpdateSystemTheme message. This is currently used in SystemMenu's
ShutdownDialog to refresh it's theme when the dialog is instantiated.
Window icons in Taskbar were previously received in WM events with
shbuf ID's. Now that Gfx::ShareableBitmap is backed by anonymous files,
we can easily switch to using those.
Now, `chres 640 480 2` can set the UI to HighDPI 640x480 at runtime. A
real GUI for changing the display factor will come later.
(`chres 640 480 2` followed by `chres 1280 960` is very fast since
we don't have to re-allocate the framebuffer since both modes use
the exact same number of physical pixels.)
It's in efficient, and it also meant we wouldn't reallocate a bigger
backing bitmap in a lowdpi->highdpi transition, leading to minor drawing
glitches after such a transition.
(Whoops!)
Problem:
- `HttpDownload()` and `HttpsDownload()` implementations are the same
except for types and certificates.
Solution:
- Follow the "Don't Repeat Yourself" mantra and de-duplicate the code
using templates.
Almost all logic stays in "logical" (unscaled coordinates), which
means the patch is small and things like DnD, window moving and
resizing, menu handling, menuapplets, etc all work without changes.
Screen knows about phyiscal coordinates and mouse handling internally is
in physical coordinates (so that two 1 pixel movements in succession can
translate to one 1 logical coordinate mouse movement -- only a single
event is sent in this case, on the 2nd moved pixel).
Compositor also knows about physical pixels for its backbuffers. This is
a temporary state -- in a follow-up, I'll try to let Bitmaps know about
their intrinsic scale, then Compositor won't have to know about pixels
any longer. Most of Compositor's logic stays in view units, just
blitting to and from back buffers and the cursor save buffer has to be
done in pixels. The back buffer Painter gets a scale applied which
transparently handles all drawing. (But since the backbuffer and cursor
save buffer are also HighDPI, they currently need to be drawn using a
hack temporary unscaled Painter object. This will also go away once
Bitmaps know about their intrinsic scale.)
With this, editing WindowServer.ini to say
Width=800
Height=600
ScaleFactor=2
and booting brings up a fully-functional HighDPI UI.
(Except for minimizing windows, which will crash the window server
until #4932 is merged. And I didn't test the window switcher since the
win-tab shortcut doesn't work on my system.) It's all pixel-scaled,
but it looks pretty decent :^)
This patch replaces the use of shbufs for GUI::Window backing stores
with the new anonymous files mechanism.
Backing bitmaps are now built on memory allocated with anon_create().
They are passed across the IPC socket as IPC::File. This means that
WindowServer now pledges "recvfd" and graphical clients need to pledge
"sendfd" to work.
To support the cached bitmap swapping optimization on the WindowServer
side, each backing store is assigned an incrementing serial number on
the client side. (This allows us to re-use an already mapped file.)
Problem:
- `HttpProtocol::start_download` and `HttpsProtocol::start_download`
implementations are the same except for a few types.
Solution:
- Follow the "Don't Repeat Yourself" mantra and de-duplicate the code
using templates.
If you don't need a file descriptor after sending it to someone over
IPC, construct it with IPC::File(fd, IPC::File::CloseAfterSending)
and LibIPC will take care of it for you. :^)
This API was a mostly gratuitous deviation from POSIX that gave up some
portability in exchange for avoiding the occasional strlen().
I don't think that was actually achieving anything valuable, so let's
just chill out and have the same open() API as everyone else. :^)