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.
This bitmap is displayed alongside the dragged text underneath the
mouse cursor while dragging.
This will be a perfect fit for dragging e.g files around. :^)
This patch enables basic drag&drop between applications.
You initiate a drag by creating a GDragOperation object and calling
exec() on it. This creates a nested event loop in the calling program
that only returns once the drag operation has ended.
On the receiving side, you get a call to GWidget::drop_event() with
a GDropEvent containing information about the dropped data.
The only data passed right now is a piece of text that's also used
to visually indicate that a drag is happening (by showing the text in
a little box that follows the mouse cursor around.)
There are things to fix here, but we're off to a nice start. :^)
Instead of passing the PIDs back and forth in a handshake "Greet"
message, just use getsockopt(SO_PEERCRED) on both sides to get the same
information from the kernel.
This is a nice little simplification of the IPC protocol, although it
does not get rid of the handshake since we still have to pass the
"client ID" from the server to each client so they know how to refer
to themselves. This might not be necessary and we might be able to get
rid of this later on.
Currently menu applets are laid out relative to the "audio rect" which
is the rect of the little audio muted state icon thingy.
There was an issue where applets would be placed at a negative X coord
if they were added to the WindowServer before the first time drawing
the menubar.
It's now possible to create a little applet window that sits inside the
system's menubar. This is done using the new CreateMenuApplet IPC call.
So far, it's possible to assign a backing store ID, and to invalidate
rects for repaint. There is no way to get the events from inside the
applet just yet.
This will allow us to move the CPU graph and audio thingy to separate
applet processes. :^)
Move this from WSCompositor::compose() to a separate run_animations()
function to keep compose() readable. We might want to add some more
animations later.
We now show a quick window outline animation when going in/out of
minimized state. It's a simple 10 frame animation at 60fps, just to
give a visual cue of what's happening with the window.
The Taskbar sends over the corresponding button rect for each window
to the WindowServer using a new WM_SetWindowTaskbarRect message.
Note that when unminimizing, we still *show* the window right away,
and don't hold off until the animation has finished. This avoids
making the desktop feel slow/sluggish. :^)
If a client sends an invalid window ID or similar to the WindowServer,
we'll now immediately mark them as misbehaving and disconnect them.
This might be too aggressive in some cases (window management, ...)
but it's just a place to start.
This matches what we're already calling the server-side subclasses
better, though we'll probably want to find some better names for the
client-side classes eventually.
This patch introduces code generation for the WindowServer IPC with
its clients. The client/server endpoints are defined by the two .ipc
files in Servers/WindowServer/: WindowServer.ipc and WindowClient.ipc
It now becomes significantly easier to add features and capabilities
to WindowServer since you don't have to know nearly as much about all
the intricate paths that IPC messages take between LibGUI and WSWindow.
The new system also uses significantly less IPC bandwidth since we're
now doing packed serialization instead of passing fixed-sized structs
of ~600 bytes for each message.
Some repaint coalescing optimizations are lost in this conversion and
we'll need to look at how to implement those in the new world.
The old CoreIPC::Client::Connection and CoreIPC::Server::Connection
classes are removed by this patch and replaced by use of ConnectionNG,
which will be renamed eventually.
Goodbye, old WindowServer IPC. You served us well :^)
Previously it was not possible to see what each thread in a process was
up to, or how much CPU it was consuming. This patch fixes that.
SystemMonitor and "top" now show threads instead of just processes.
"ps" is gonna need some more fixing, but it at least builds for now.
Fixes#66.
Clicking on this icon toggles the AudioServer muted state.
It currently does not react to muted state changes caused by other
programs, since it has no way of learning about those from AudioServer,
other than performing a synchronous IPC call (GetMuted), which we don't
want to be doing in the WindowServer :^)
When a window is being resized, its size may differ from the size of its backing
store. In this case, peek at the direction the window is being resized in, and
render the backing store at the same place as it was previously.
https://github.com/SerenityOS/serenity/issues/52
When a window is being interactively resized, there are several rules
beyond the actual mouse movement that can impact the new size of the
window, such as its size increments and minimum size limit.
Move the placement logic after applying all the sizing logic, so that
whatever final size the window ends up with, the sides of the window
that do move are the ones that the user is dragging.
https://github.com/SerenityOS/serenity/issues/52
This patch adds pthread_create() and pthread_exit(), which currently
simply wrap our existing create_thread() and exit_thread() syscalls.
LibThread is also ported to using LibPthread.
Now that the WindowServer's menu is the primary way to start apps,
it is especially noticable that it leaks the /dev/fb0 fd to the apps
that it spawns. Fix that by opening it with O_CLOEXEC.
The Launcher's functionality has been replaced by the app shortcuts in
the system menu.
There were various window management hacks to ensure that the launcher
stayed below all other windows while also being movable, etc.
Separators can't have identifiers associated with them, so it's not
possible to react meaningfully to their activation. Don't send messages
about it to avoid confusing the clients.
Let the global menu bar be either "open" or "closed". Clicking on one
of the menus in the menu bar toggles the state.
This ends up simpler and more intuitive than what we had before.
This patch moves a whole lot of the menu logic from WSWindowManager to
its proper home in WSMenuManager.
We also get rid of the "close_current_menu()" concept which was easily
confused in the presence of submenus. All operations should now be
aware of the menu stack instead. (The concept of a single, current menu
made a lot more sense when there were no nested menus.)
If the .af file for an app contains the App/Category key, we'll now put
it in a submenu of the system menu, together with all the other apps in
that same category. This is pretty neat! :^)