The clock menu applet was causing pixel ghosting at some seemingly
arbitrary location on the desktop because the background paint logic
tries to avoid painting any part of the background that's covered by
an opaque window.
Since the code was using any_opaque_window_contains_rect() to check
this, we were not considering the window's *type*. (Menu applets are
still windows, but they are of the special type "MenuApplet" and do
not participate in normal compositing.)
The fix is to use for_each_visible_window_from_back_to_front() instead
of for_each_window() :^)
Fixes#1022.
Menus are now owned by menu manager instead of being split between the
window manager and menu manager. If the window server wants to change
a menu, or call menu related functionality, this will need to be done
through the menu manager.
Further refactoring is likely needed, but this seems like a good start
for seperating menu logic from window logic.
Previously we would be left with a menu stack containing nulled-out
WeakPtr's to menus in the now-disconnected clients.
This was tripping up an assertion when clicking anywhere after shutting
down a program while it had a menu open.
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.
This is done here rather than pick_new_active_window() so that when
there are no other windows to focus but the previous window hasn't
been removed (just minimized), the menu bar remains on that client.
Also make sure we send out the WM event for window deactivations.
This fixes an issue where the taskbar button for a window would appear
depressed, even after the window was deactivated.
Instead of just boosting the main thread, let's boost all threads in
the currently active client process.
This avoids creating internal priority inversion problems in clients.
When the currently active (foreground) window is owned by a client,
we now apply a +10 priority boost to the client's main thread.
You normally want the window you're interacting with to be responsive,
so this little boost allows it to run a bit sooner and more often. :^)
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.
Build them if they don't exist, but don't care about them being
newer or older than the target.
I believe this is what was causing build loops where IPCCompiler was
being run a second time, rebuilding its .h file, then a library
would depend on that .h file and get re-archived, then an
application would need relinking, and something in that whole
process would trigger IPCCompiler running again touching its .h
file.
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. :^)
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! :^)
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! :^)
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.
When we're in a drag, we're no longer concerned with streaming mouse
events to the window that initiated the drag, so just clear the active
input window pointer.
This fixes an issue where you'd have to click once after drag and drop
in order to "release" the mouse from the active input window.
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.
This patch introduces the second MenuApplet: Audio. To make this work,
menu applet windows now also receive mouse events.
There's still some problem with mute/unmute via clicking not actually
working, but the call goes from the applet program over IPC to the
AudioServer, where something goes wrong with the state change message.
Need to look at that separately.
Anyways, it's pretty cool to have more applets running in their own
separate processes. :^)
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 :^)
Windows that are being moved around by the user are now called "moving"
windows instead of "dragging" windows, to avoid confusion with the
drag and drop stuff.