Summary:
TaskGroupingProxyModel uses a simple QVector<QVector<int>> populated
with source model row indices to represent the task group tree. To
implement QAbstractItemModel::parent(), its implementation of index()
encodes row indices of the top-level vector into the internal ids of
child item model indices. This allows parent() to produce the parent
model index by simply decoding the parent row from the passed-in child
index and call index() with that row.
Top-level row indices shift up and down as the list of top-level items
changes, invalidating those internal ids. QModelIndex is not meant to
be stored, and the proxy model does take care of updating any persis-
tent model indexes with new ids, so this should be fine.
However, where it falls apart is that as internal ids are invalidated,
a QSortFilterProxyModel on top of this proxy (i.e. TasksModel) may end
up with multiple indexes with identical internal ids in its mappings,
causing it to mess up its mappings as it uses them (e.g. taking things
from them). This causes the often-reported crash/assert there.
The fix is to refactor index()/parent() not to rely on row indices as
internal ids, but instead use pointers to internal data structures
instead.
This patch achieves this by changing the map to QVector<QVector<int> *>.
This screams fugly, but the alternative would basically just be to
create some wrapper struct to hide the fugly appeareance a little,
which I don't think is worth it.
On the flip side, it saves a QVector::replace() call as a multable
vector iterator can work directly on a vector without making a copy,
and it's now no longer necessary to manually update the persistent
model indices beyond what endRemoveRows() does implicitly.
BUG:381006
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D7139
Summary:
Windows we can't find an app icon for using the normal means
get the icon used by the windowing system in the Task Manager.
This fallback icon was then not updated when changed on the
window, only occasionally as a side-effect of cache evictions
and model data requests.
This patch notes which windows hit the fallback path, and for
those windows evicts the cache when the icon changes on the
window, causing it to be re-retrieved from the windowing system
as views respond to the dataChanged signal for the decoration
role.
Evicting the entire cache is a little bit costly, but:
- This is a fallback codepath.
- Apps conventionally update title and icon in one go, meaning
the cache is often already getting evicted anyway.
- Icons don't change that often.
BUG:383017
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D7092
This is done in XWindowTasksModel and WaylandTasksModel but was forgotten in LauncherTasksModel.
Differential Revision: https://phabricator.kde.org/D6869
Summary:
Also better sanity-checking of found services being app services
all around.
I'm not particularly happy about adding more X11 code outside of
XWindowTasksModel, but it means greater code reuse (in something that
has experienced unwelcome drift before) and there's a precedent in
LauncherTasksModel.
Reviewers: #plasma, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6358
Summary:
Otherwise we:
* ... don't get startup notifications.
BUG:381500
* ... don't contribute data to recent/most used apps.
This is a surprisingly large oversight.
Reviewers: #plasma
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6354
Summary:
The pinned launchers that are assigned to other activities
will have a -1 as the order. We should not forget them
when saving to the configuration file.
Reviewers: hein, mart
Reviewed By: hein
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5933
Summary:
The pinned launchers that are assigned to other activities
will have a -1 as the order. We should not forget them
when saving to the configuration file.
Reviewers: hein, mart
Reviewed By: hein
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5933
Summary:
This factors the app identification heuristic out of XWindowTasksModel
and turns it into generic code in TaskTools, producing a URL from a set
of window metadata bits. The key metadata is the 'appId', which is the
classClass part of WM_CLASS on X11 and PlasmaWindow::appId on Wayland -
which KWin sets to the former for XWayland clients. The result is much
improved support for XWayland clients in the Wayland session, with most
X clients now identified correctly.
As a side effect, the Wayland model gains access to the X model's much
superior code for grabbing a suitable icon, with PlasmaWindow::icon now
serving only as a fallback, similar to KWindowSystem::icon in the X
model.
Moving the code to TaskTools also means it now sports nice API docs.
The heuristic has seen some work as well, namely adding two passes that
try to parse the appId as a path to a desktop file, which we've never
seen on X11 but is common on Wayland - this heuristic was previously in
appDataFromAppId, which has been removed here since the shared heuristic
now satisfies this case.
Further, an old codepath handling kcmshell in a special way has been
removed. This is no longer necessary as we have better ways to tell
libtaskmanager about the KCM KService now, such as the .desktop file
window hint on X11 and a reliable appId on Wayland.
This patch also fixes some bugs around app data cache eviction and
telling model clients about data changes when cache eviction happens.
The X model didn't use to evict the cache and refresh when the
taskmanagerrulesrc file was changed at runtime, and the refresh for
sycoca changes didn't refresh the LauncherUrlWithoutIcon role. It does
now, and the Wayland model - which has gained taskmanagerrulesrc support
by way of the shared heuristic - now behaves in the same way.
The combined changes achieve near behavior parity between the X
and Wayland models when it comes to identifying apps by window meta
data, with the only exception being XWayland clients that need to be
identified by the (incorrectly used by the client developer) instance
name part of the WM_CLASS window property, which we can't access (this
case is so rare it's not worth handling at this time).
Depends on D5747, D5755.
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5818
Summary:
This introduces a TryIgnoreRuntimes key in taskmanagerrulesrc's Settings
group that can be used to list known runtime executables that can be
ignored when trying to identify the application owning a window by the
command line of the associated process.
A concrete example is the Frozen Bubble application. Frozen Bubble
installs a frozen-bubble.desktop with Exec=frozen-bubble, yet its
WM_CLASS is ("perl", "perl") and its command line is as follows:
/usr/bin/perl /usr/bin/frozen-bubble
The existing servicesFromPid() (now split into servicesFromPid() and
servicesFromCmdLine()) does not find the frozen-bubble service because
it works with the leading executable in the command line.
In this patch, TryIgnoreRuntimes is introduced with a default of
"perl". In the new code, after the initial command line matching pass
fails, TryIgnoreRuntimes is checked for whether the leading command
line executable is on the list, and if so, a second command line
matching pass is run with the remainder of the process' command line,
now succeeding.
Note that the approach of "try one more thing" rather than checking
against TryIgnoreRuntimes first is deliberate: The Exec= key in many
.desktop files contains a complete command line prefixed with the
runtime executable. In those cases we don't want to ignore the runtime
executable, or matching would fail.
To complement this, the "perl" WM_CLASS is added to the
MatchCommandLineFirst rc key. Due to the shoddy metadata Frozen
Bubble already ended up in servicesFromPid() regardless, but this
saves some busywork for this WM_CLASS, which can reliably be presumed
bad.
The patch also fixes a small logic error in the match-command-line-
without-arguments block, where the result of a KServiceTypeTrader
query was ignored and immediately overridden by another.
Reviewers: #plasma, davidedmundson, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5522
Summary:
This is implemented by TasksModel and allows clients to reliably
query whether a row has an associated launcher. Useful for things
like Pin/Unpin action state or layout decisions.
Previously clients would have to reimplement something like
TaskTools::appsMatch on top of the model, which we absolutely do
not want to do - there should only be one copy of the app matching
logic for consistency's sake. In practice clients would do things
like fetch LauncherUrl and run it by launcherPosition(), which
omits appsMatch's AppId comparision, as an example of such unwated
drift. This approach also avoids the large performance overhead
involved.
The role is not implemented by the single-type or munging tasks
models as it has no use there.
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5504
Summary:
Previously we updated the prop after checking for
AbstractTasksModel::IsDemandingAttention on window closure, but
as the window is gone, we can't actually get state for it anymore,
so we always need to update.
To make up for it, this patch also optimizes the prop updates to occur
only once per insert/remove batch - this is a bit academic because
the source models currently only insert single rows at a time, but
it's good hygiene.
BUG:378254
Reviewers: #plasma, mart
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D5261
Summary:
We currently match Krita by Name. It's classClass is "krita",
but its DesktopEntryName is org.kde.krita.desktop. However,
Krita also installs numerous additional .desktop entries to
associate more file types by itself, all of which match by
name, and the first one in the list isn't the right one. All
of those extra .desktop files are NoDisplay=true however, so
we can filter them out, which brings the match list down to
the one and only .desktop file we care for.
Reviewers: #plasma, broulik, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4928
Summary:
The new activity-aware implementation of
LauncherTasksModel::setLauncherList() would only accept the passed list
when it changed any activities associations, not when the order changed.
This would effectively turn TasksModel::move involving launcher tasks
into a no-op.
Rearranging launchers works like this:
1. A client calls TasksModel::move one or many times. TasksModel::move
updates TasksModel's internal sort mapping and implements it, causing
a visible order change in any views.
2. When it is done calling move(), the client calls
TasksModel::syncLaunchers. TasksModel::syncLaunchers calls
LauncherTasksModel::setLauncherList with a new list derived from
its sort mapping, and updates its sort mapping in expectation of
row indices changing in the launcher tasks source model.
Due to the above bug, the sort mapping would be adjusted in expectation
of changes the launcher tasks model would not actually do, appearing to
undo the moves the next time a view is updated from source data.
CCMAIL:ivan.cukic@kde.org
Reviewers: #plasma, davidedmundson, mart
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4749
Summary:
WM_CLASS instance and general classes are checked against StartupWMClass
prior to most rewrite and mapping rules, and prior to the DesktopEntryName
and Name checks.
This matches the fd.o spec more closely and makes Chrome Apps and
LibreOffice work without special mapping rules, which is also a speed
win.
Reviewers: #plasma, davidedmundson, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4706
We only matched for the "Default" suffix which is the default profile but this breaks
when having apps installed in different profiles where they get e.g. "Profile_1" suffix.
BUG: 376695
FIXED-IN: 5.9.3
Differential Revision: https://phabricator.kde.org/D4680
Summary:
What happens:
* Activity switch calls invalidateFilter on TaskFilterProxyModel,
which may remove rows in response.
* Up the proxy chain, TasksModel may ask LauncherTasksModel to
emit dataChanged for its contents in response to the row removal,
to cause its own filtering to re-evaluate the launchers for the
life cycle logic.
* This can cause TFPM to do more filtering before invalidateFilter
has actually returned, causing trip-ups such as duplicated rows
in the proxy.
* Eventually the corrupted maps cause a memory corruption crash.
This patch changes step 2 to "find the launchers in the TFPM (the
direct source model) and ask for a dataChanged for each". This
costs us a loop and accesses to IsLauncher, but on the other hand
fixes the crash and avoids a lot of filtering and mapping work
between LTM and up to and including TFPM. It's also just better
code to ask for the dataChanged only from the model we need it
from.
BUG:376055
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4631
Summary:
Alphabetical sorting currently compares a concatenation of
"AppName" (determined by heuristic) and Qt::DisplayRole (usually
the window title) using QString::localeAwareSort. This reflects
that the motivation behind alphabetical sorting is generally to
keep windows belonging to the same app grouped together and then
order those groups alphabetically.
The current code achieves this, but the particulars turn out to
negatively impact users of multi-windowed apps that frequently
change window titles in ways that impact sorting, particularly
tabbed web browsers. Switching between tabs may change the order
of browser windows on the Task Manager. Multiple instances of
feedback suggest this is jarring and unexpected, despite
technically being alphabetical.
This patch changes behavior as follows:
1. Instead of comparing "<App Name><DisplayRole>" it will try to only
compare "<App Name>", falling back to "<DisplayRole>" if the app
name can't be determined.
2. If two tasks compare to equal in the above, it will fall back to
source model row order, i.e. creation/append sorting.
This still achieves the primary goal laid out above while
keeping the sort order within an app "group" stable when using
alphabetical sorting.
BUG:373698
An alternative means to achive this behavior would be via existing
Task Manager settings. To wit:
1. Enable grouping
2. Disable group popups, so groups are instead maintained inline
on the widget
I'm actually considering suggesting the above (plus changing
sorting to Manual) as new default settings for 5.10 - but in
the meantime it still makes sense to tune the alphabetical
sorting mode in this way, and put the improved behavior into
5.8 and 5.9 to address user feedback earlier.
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4469
Summary:
syncLaunchers() is called after drag operations end to write the order
of launchers in the all-capping TasksModel to the LauncherTaskModel
source model. The per-activity launcher pinning work recently broke
this by changing the model that's looped over.
Reviewers: #plasma, ivan, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4608
Summary:
Hitting again a bug where switching desktops shows a delay of several seconds
before the taskbar updates, I noticed that this code path was called 81
times in 7 seconds (!) for kmail (maybe because I start it from cmdline
rather than via a .desktop file).
After the 4 slow calls to KWindowSystem::icon it seems definitely worth
it to cache the result.
Overall the main performance bug is still there though, switching
desktops is still slow, but now all backtraces show QML triggered
by model/view dataChanged signals, no idea yet, other than hoping
for the pending QSFPM patches to help with this (no need to re-sort
when the dataChanged roles are unrelated to the roles used for sorting).
Reviewers: hein
Reviewed By: hein
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4600
Summary:
Versions of VirtualBox packaged on Neon and Fedora now have
a proper WM_CLASS:
Fedora: WM_CLASS(STRING) = "VirtualBox", "VirtualBox"
Neon: WM_CLASS(STRING) = "Qt-subapplication", "VirtualBox"
And install a matching virtualbox.desktop.
We can therefore drop this rule.
BUG:350468
Side note: The rule should actually still have worked, but
for some reason KServiceTypeTrader refuses to match a .desktop
with 'Exec=VirtualBox %U' when we query for 'VirtualBox', as
extracted from cmdline. I'm talking to dfaure about it.
Reviewers: #plasma, broulik
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D4346
Summary:
It turns out that Chrome under certain conditions will change its
window metadata as it quits, causing a race we sometimes lose, failing
to reveal the associated launcher because we can no longer match it
to the window at window closing time. Instead we are now forced to
re-check all launchers after the window is gone. As a speed optimi-
zation we only consider top-level windows (and startups) as being in
a group implies matching siblings.
In addition this refactoring eliminates a use of Qt::QueuedConnection
that allowed for an unpredictable event loop spin inbetween things.
BUG:365617
Reviewers: davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3950
Summary:
It turns out that Chrome under certain conditions will change its
window metadata as it quits, causing a race we sometimes lose, failing
to reveal the associated launcher because we can no longer match it
to the window at window closing time. Instead we are now forced to
re-check all launchers after the window is gone. As a speed optimi-
zation we only consider top-level windows (and startups) as being in
a group implies matching siblings.
In addition this refactoring eliminates a use of Qt::QueuedConnection
that allowed for an unpredictable event loop spin inbetween things.
BUG:365617
Reviewers: davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3950
Summary:
This makes the AdditionalRoles enum available to Qt Quick. Useful for
calling data() TasksModel from inside QML, which uses AbstractTasksModel
roles but doesn't actually inherit from AbstractTasksModel.
The reason TasksModel doesn't inherit from AbstractTasksModel is
because it inherits from QSortFilterProxyModel, and it doesn't fly
to multiple-inherit from two QObject-derived classes. This is also
why AdditionalRoles can't be moved to AbstractTasksModelIface easily.
The VDG is working on tooltip changes that require this.
Reviewers: #plasma, davidedmundson, subdiff
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3641
Summary:
As this happens the screen filtering higher up in the proxy chain
culimating in TasksModel needs to be re-executed, as it compares
ScreenGeometry against a property value set on the model. Without
this update, tasks may disappear from views using TasksModel.
Mapping the trigger conditions to affected rows is deliberately
maximally coarse; see implementation comment in code.
BUG:373075
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3628
Summary:
This adds a new data role "ChildCount" to AbstractTasksModel and
implements it in TaskGroupingProxyModel.
The purpose of this data role is as a means of signalling to a Qt
Quick delegate for a top-level row that a property of the item -
namely the number of children it has - has changed. Qt Quick's poor
support for tree models makes the existing way of signaling this
(rowsInserted) prohibitive to use.
The Task Manager applet needs this info because it's in charge of
telling the window manager about the screen coordinates of window
delegates (through support code in this library). When a window is
directly added to an existing group, there is no new delegate
created, nor does the existing delegate change position. An
increase of ChildCount will be used in this case to decide to
publish delegate geo for the new window.
CCBUG:372699
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3482
Summary:
This adds a new data role "ChildCount" to AbstractTasksModel and
implements it in TaskGroupingProxyModel.
The purpose of this data role is as a means of signalling to a Qt
Quick delegate for a top-level row that a property of the item -
namely the number of children it has - has changed. Qt Quick's poor
support for tree models makes the existing way of signaling this
(rowsInserted) prohibitive to use.
The Task Manager applet needs this info because it's in charge of
telling the window manager about the screen coordinates of window
delegates (through support code in this library). When a window is
directly added to an existing group, there is no new delegate
created, nor does the existing delegate change position. An
increase of ChildCount will be used in this case to decide to
publish delegate geo for the new window.
CCBUG:372699
Reviewers: #plasma, davidedmundson
Subscribers: plasma-devel
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D3482
Depending on the distribution, Chromium identifies itself as "chromium" or "chromium-browser". Account for this.
CHANGELOG: Chromium WebApp windows are no longer treated as Chromium browser windows in task manager
Differential Revision: https://phabricator.kde.org/D3450