And remove the now-redundant members m_scrubbing, m_scrubber_in_use,
and m_automatic_scrolling_kind.
This also made it clear that we weren't canceling the autoscroll
timer if the scrollbar got disabled while it was scrolling, so
this fixes that too.
The motivation for this change is twofold:
- Returning a JS::Value is misleading as one would expect it to carry
some meaningful information, like maybe the error object that's being
created, but in fact it is always empty. Supposedly to serve as a
shortcut for the common case of "throw and return empty value", but
that's just leading us to my second point.
- Inconsistent usage / coding style: as of this commit there are 114
uses of throw_exception() discarding its return value and 55 uses
directly returning the call result (in LibJS, not counting LibWeb);
with the first style often having a more explicit empty value (or
nullptr in some cases) return anyway.
One more line to always make the return value obvious is should be
worth it.
So now it's basically always these steps, which is already being used in
the majority of cases (as outlined above):
- Throw an exception. This mutates interpreter state by updating
m_exception and unwinding, but doesn't return anything.
- Let the caller explicitly return an empty value, nullptr or anything
else itself.
Note that m_hovered_component is only updated on mouse move, not while
just keeping left down. It's arguably wrong to update it on mouse move
while the mouse is down, I'll probably change things so that it doesn't
update there either.
The behavior on click-in-gutter-keep-left-down-then-move-mouse varies
a surprising amount between platforms. This implements the macOS
behavior where the scrubber follows the mouse direction while scrolling
by pages. (To be precise, it's the macOS behavior of Finder and Preview,
Safari has Windows's scrollbar behavior).
On Windows, the first click locks in the scroll direction and then
dragging the mouse off the scrubber in that direction makes the
scroll continue, but dragging it off the other direction has no effect.
I see no reason for that behavior.
Rather than disable and re-enable the timer, always keep it active
and make it do collision checks to decide if it should have an effect.
This is because set_automatic_scrolling_active(true) calls the
timeout callback immediately before starting the timer, and
when clicking the gutter this callback could disable the timer
again (if the first page scroll put the scrubber under the cursor).
Intead of making set_automatic_scrolling_active() work when it's
called reentrantly (which is easy: just swap the order of
on_automatic_scrolling_timer_fired() and timer->start() so that
on_automatic_scrolling_timer_fired() can immediately stop the
timer again, but it's confusing), make the timer check if it
should do anything.
This is keyed off m_last_mouse_position instead of
m_hovered_component because m_hovered_component is a visual state
and we arguably shouldn't modify it while the left mouse button
is down (as it indicated what part is activated on click).
Most callers of set_automatic_scrolling_active() also change
m_automatic_scrolling_kind, and it makes it possible to make timer
behavior dependent on the autoscroll kind later.
It's slightly less code, and m_scrubber_in_use is now set correctly
when shift-clicking, keeping the mouse button down, and then
dragging the throbber.
The shift-click brings the scrubber under the cursor, and then
the scrubber_rect().contains() condition is true and both scrubber
drags and shift-click-drags are handled the same naturally.
Consider the following scenario:
if(condition)
FOO();
else
bar();
Suppose FOO is defined as follows:
#define FOO() { bar(); baz(); }
Then it expands to the following:
if(condition)
// Syntax error, we are not allowed to put a semicolon at the end.
{ bar(); baz(); };
else
bar();
If we define FOO as follows:
#define FOO() do { bar(); baz(); } while(false)
Then it expands to the following:
if(condition)
do { bar(); baz(); } while(false);
else
bar();
Which is correct.
MemoryManager cannot use the Singleton class because
MemoryManager::initialize is called before the global constructors
are run. That caused the Singleton to be re-initialized, causing
it to create another MemoryManager instance.
Fixes#3226
Rather than hardcoding where the kmalloc pool should be, place
it at the end of the kernel image instead. This avoids corrupting
global variables or other parts of the kernel as it grows.
Fixes#3257
When trying to scroll up on virtualizers that don't use the VMware
backdoor and instead use PS2MouseDevice, it would actually scroll
down rapidly.
Looking into it, the mouse delta for scrolling down was 1 and 15
for scrolling up. 15 is suspiciously -1 for a nibble.
According to https://isdaman.com/alsos/hardware/mouse/ps2interface.htm
the Z is actually 4 bits for Intellimouse.
This fixes scrolling up on virtualizers such as VirtualBox.
This patchset adds a few getters/setters to AbstractTableView to make
its looks more customisable:
- Header width & text alignment
- Default column width
- Ability to disable selected row highlighting
The tzset documentation says that TZ allows a per-second local timezone,
so don't be needlessly clever here.
No observable behavior difference at this point, but if we ever
implement tzset, this will have a small effect.
Set member variables after calling mktime(), which canonicalizes
out-of-range values.
With this, DateTime::create(2020, 13, ...) will return a DateTime
on Jan 2021 (assuming the other parameters are in range).
mktime() is supposed to fill in tm_wday and tm_yday, and it
it's supposed to canonicalize out-of-range values (that is,
"Jan 31" is turned into "Feb 1").
Instead of making the straightfoward tm_to_time() implementation
more complicated, just make it call time_to_tm() once the timestamp
is computed to break it back down ot (canonical) tm entries.