From 9334435b807a67c22921ff0620d003eb8e97849c Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sat, 14 Sep 2024 18:30:25 +0200 Subject: [PATCH 01/17] feat: implement stub to map tablet to full desktop area Plasma expects these functions to exist in the D-Bus specs. For now we implement them only as a stub. --- como/input/dbus/device.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/como/input/dbus/device.h b/como/input/dbus/device.h index f3e54a5f6..09fe19995 100644 --- a/como/input/dbus/device.h +++ b/como/input/dbus/device.h @@ -153,6 +153,23 @@ class COMO_EXPORT device : public QObject Q_PROPERTY(bool supportsOutputArea READ supportsOutputArea CONSTANT) Q_PROPERTY(QRectF defaultOutputArea READ defaultOutputArea CONSTANT) Q_PROPERTY(QRectF outputArea READ outputArea WRITE setOutputArea NOTIFY outputAreaChanged) + Q_PROPERTY(bool defaultMapToWorkspace READ defaultMapToWorkspace CONSTANT) + Q_PROPERTY(bool mapToWorkspace READ isMapToWorkspace WRITE setMapToWorkspace NOTIFY + mapToWorkspaceChanged) + + bool defaultMapToWorkspace() const + { + return false; + } + + bool isMapToWorkspace() const + { + return false; + } + + void setMapToWorkspace(bool /*mapToWorkspace*/) + { + } public: explicit device(input::control::keyboard* control, QObject* parent); @@ -298,6 +315,7 @@ class COMO_EXPORT device : public QObject void scrollFactorChanged(); void clickMethodChanged(); void outputAreaChanged(); + void mapToWorkspaceChanged(); }; } From 83d5cba64d4c986fafa99f138ae3173488f9171f Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 11 Apr 2024 14:49:33 +0100 Subject: [PATCH 02/17] refactor: port to simpler PlasmaWindow Plasma::Dialog contains logic that we don't want for a kwin window and is considered deprecated. Dialog uses the width of the main item which results in an unavoidable binding loop. PlasmaWindow allows us to propagate implicit sizes upwards correctly. BUG: 420757 --- .../desktopchangeosd/package/contents/ui/osd.qml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/scripts/desktopchangeosd/package/contents/ui/osd.qml b/plugins/scripts/desktopchangeosd/package/contents/ui/osd.qml index f3eaef917..0c0cf0d3b 100644 --- a/plugins/scripts/desktopchangeosd/package/contents/ui/osd.qml +++ b/plugins/scripts/desktopchangeosd/package/contents/ui/osd.qml @@ -10,12 +10,13 @@ import org.kde.kirigami 2.20 as Kirigami import org.kde.ksvg 1.0 as KSvg import org.kde.kwin -PlasmaCore.Dialog { +PlasmaCore.Window { id: dialog - location: PlasmaCore.Types.Floating visible: false flags: Qt.X11BypassWindowManagerHint | Qt.FramelessWindowHint - outputOnly: true + + width: mainItem.implicitWidth + leftPadding + rightPadding + height: mainItem.implicitHeight + topPadding + bottomPadding mainItem: Item { function loadConfig() { @@ -35,8 +36,8 @@ PlasmaCore.Dialog { property int animationDuration: 1000 property bool showGrid: true - width: dialogItem.showGrid ? view.itemWidth * view.columns : Math.ceil(textElement.implicitWidth) - height: dialogItem.showGrid ? view.itemHeight * view.rows + textElement.height : textElement.height + implicitWidth: dialogItem.showGrid ? view.itemWidth * view.columns : Math.ceil(textElement.implicitWidth) + implicitHeight: dialogItem.showGrid ? view.itemHeight * view.rows + textElement.implicitHeight : textElement.implicitHeight Kirigami.Heading { id: textElement From 237b3a049dbd7ea661334fde553ba07b4f4ce25b Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 21 May 2024 14:27:52 +0300 Subject: [PATCH 03/17] refactor: drop xcursor write hook It's unused. --- como/input/extern/xcursor.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/como/input/extern/xcursor.c b/como/input/extern/xcursor.c index 169753244..104a2a012 100644 --- a/como/input/extern/xcursor.c +++ b/como/input/extern/xcursor.c @@ -188,7 +188,6 @@ typedef struct _XcursorFile XcursorFile; struct _XcursorFile { void *closure; int (*read) (XcursorFile *file, unsigned char *buf, int len); - int (*write) (XcursorFile *file, unsigned char *buf, int len); int (*seek) (XcursorFile *file, long offset, int whence); }; @@ -556,13 +555,6 @@ _XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) return fread (buf, 1, len, f); } -static int -_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len) -{ - FILE *f = file->closure; - return fwrite (buf, 1, len, f); -} - static int _XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) { @@ -575,7 +567,6 @@ _XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) { file->closure = stdfile; file->read = _XcursorStdioFileRead; - file->write = _XcursorStdioFileWrite; file->seek = _XcursorStdioFileSeek; } From 85b362a5f423e950995fc392121f60211f2b4f3f Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 21 May 2024 15:10:41 +0300 Subject: [PATCH 04/17] refactor: load Xcursor themes using QFile This improves the integration of the XcursorTheme class with the rest of the Qt ecosystem, for example it should be possible to load cursor themes from Qt resources. --- como/input/extern/xcursor.c | 60 +++------------------------- como/input/extern/xcursor.h | 11 ++++- como/input/wayland/xcursor_theme.cpp | 24 ++++++++++- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/como/input/extern/xcursor.c b/como/input/extern/xcursor.c index 104a2a012..8e9f48baf 100644 --- a/como/input/extern/xcursor.c +++ b/como/input/extern/xcursor.c @@ -183,14 +183,6 @@ typedef struct _XcursorComment { #define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) #define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ -typedef struct _XcursorFile XcursorFile; - -struct _XcursorFile { - void *closure; - int (*read) (XcursorFile *file, unsigned char *buf, int len); - int (*seek) (XcursorFile *file, long offset, int whence); -}; - typedef struct _XcursorComments { int ncomment; /* number of comments */ XcursorComment **comments; /* array of XcursorComment pointers */ @@ -259,7 +251,7 @@ XcursorImagesDestroy (XcursorImages *images) static XcursorBool _XcursorReadUInt (XcursorFile *file, XcursorUInt *u) { - unsigned char bytes[4]; + uint8_t bytes[4]; if (!file || !u) return XcursorFalse; @@ -321,7 +313,7 @@ _XcursorReadFileHeader (XcursorFile *file) return NULL; skip = head.header - XCURSOR_FILE_HEADER_LEN; if (skip) - if ((*file->seek) (file, skip, SEEK_CUR) == EOF) + if (!(*file->skip) (file, skip)) return NULL; fileHeader = _XcursorFileHeaderCreate (head.ntoc); if (!fileHeader) @@ -352,10 +344,9 @@ _XcursorSeekToToc (XcursorFile *file, XcursorFileHeader *fileHeader, int toc) { - if (!file || !fileHeader || \ - (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF) - return XcursorFalse; - return XcursorTrue; + if (!file || !fileHeader) + return XcursorFalse; + return (*file->seek) (file, fileHeader->tocs[toc].position); } static XcursorBool @@ -501,7 +492,7 @@ _XcursorReadImage (XcursorFile *file, return image; } -static XcursorImages * +XcursorImages * XcursorXcFileLoadImages (XcursorFile *file, int size) { XcursorFileHeader *fileHeader; @@ -547,42 +538,3 @@ XcursorXcFileLoadImages (XcursorFile *file, int size) } return images; } - -static int -_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) -{ - FILE *f = file->closure; - return fread (buf, 1, len, f); -} - -static int -_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) -{ - FILE *f = file->closure; - return fseek (f, offset, whence); -} - -static void -_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) -{ - file->closure = stdfile; - file->read = _XcursorStdioFileRead; - file->seek = _XcursorStdioFileSeek; -} - -XcursorImages * -XcursorFileLoadImages (const char *file, int size) -{ - XcursorFile f; - XcursorImages *images; - - FILE *fp = fopen(file, "r"); - if (!fp) - return NULL; - - _XcursorStdioFileInitialize (fp, &f); - images = XcursorXcFileLoadImages (&f, size); - fclose(fp); - - return images; -} diff --git a/como/input/extern/xcursor.h b/como/input/extern/xcursor.h index 4837cc956..4fec64e60 100644 --- a/como/input/extern/xcursor.h +++ b/como/input/extern/xcursor.h @@ -60,8 +60,17 @@ typedef struct _XcursorImages { XcursorImage **images; /* array of XcursorImage pointers */ } XcursorImages; +typedef struct _XcursorFile XcursorFile; + +struct _XcursorFile { + void *closure; + int (*read) (XcursorFile *file, uint8_t *buf, int len); + XcursorBool (*skip) (XcursorFile *file, long offset); + XcursorBool (*seek) (XcursorFile *file, long offset); +}; + XcursorImages * -XcursorFileLoadImages (const char *file, int size); +XcursorXcFileLoadImages (XcursorFile *file, int size); void XcursorImagesDestroy (XcursorImages *images); diff --git a/como/input/wayland/xcursor_theme.cpp b/como/input/wayland/xcursor_theme.cpp index 5e288b96c..a77bc583d 100644 --- a/como/input/wayland/xcursor_theme.cpp +++ b/como/input/wayland/xcursor_theme.cpp @@ -82,8 +82,28 @@ std::chrono::milliseconds xcursor_sprite::delay() const static QList load_cursor(QString const& file_path, int target_size, double device_pixel_ratio) { - auto images - = XcursorFileLoadImages(QFile::encodeName(file_path), target_size * device_pixel_ratio); + QFile file(file_path); + if (!file.open(QFile::ReadOnly)) { + return {}; + } + + XcursorFile reader{ + .closure = &file, + .read = [](XcursorFile* file, uint8_t* buffer, int len) -> int { + QFile* device = static_cast(file->closure); + return device->read(reinterpret_cast(buffer), len); + }, + .skip = [](XcursorFile* file, long offset) -> XcursorBool { + QFile* device = static_cast(file->closure); + return device->skip(offset) != -1; + }, + .seek = [](XcursorFile* file, long offset) -> XcursorBool { + QFile* device = static_cast(file->closure); + return device->seek(offset); + }, + }; + + auto images = XcursorXcFileLoadImages(&reader, target_size * device_pixel_ratio); if (!images) { return {}; } From c06f61e7218741f3eaed12f3c58d21b9ebdb5a37 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 21 May 2024 15:29:39 +0300 Subject: [PATCH 05/17] style: reformat xcursor.{h,c} --- como/input/extern/xcursor.c | 466 +++++++++++++++++------------------- como/input/extern/xcursor.h | 50 ++-- 2 files changed, 250 insertions(+), 266 deletions(-) diff --git a/como/input/extern/xcursor.c b/como/input/extern/xcursor.c index 8e9f48baf..a2ffc4429 100644 --- a/como/input/extern/xcursor.c +++ b/como/input/extern/xcursor.c @@ -28,17 +28,17 @@ #define _DEFAULT_SOURCE #include "xcursor.h" +#include #include #include #include -#include /* * From libXcursor/include/X11/extensions/Xcursor.h */ -#define XcursorTrue 1 -#define XcursorFalse 0 +#define XcursorTrue 1 +#define XcursorFalse 0 /* * Cursor files start with a header. The header @@ -71,7 +71,7 @@ * CARD32 position absolute file position */ -#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ +#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ /* * Current Xcursor version number. Will be substituted by configure @@ -81,32 +81,32 @@ #define XCURSOR_LIB_MAJOR 1 #define XCURSOR_LIB_MINOR 1 #define XCURSOR_LIB_REVISION 13 -#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \ - (XCURSOR_LIB_MINOR * 100) + \ - (XCURSOR_LIB_REVISION)) +#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + (XCURSOR_LIB_MINOR * 100) + (XCURSOR_LIB_REVISION)) /* * This version number is stored in cursor files; changes to the * file format require updating this version number */ -#define XCURSOR_FILE_MAJOR 1 -#define XCURSOR_FILE_MINOR 0 -#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) -#define XCURSOR_FILE_HEADER_LEN (4 * 4) -#define XCURSOR_FILE_TOC_LEN (3 * 4) - -typedef struct _XcursorFileToc { - XcursorUInt type; /* chunk type */ - XcursorUInt subtype; /* subtype (size for images) */ - XcursorUInt position; /* absolute position in file */ +#define XCURSOR_FILE_MAJOR 1 +#define XCURSOR_FILE_MINOR 0 +#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) +#define XCURSOR_FILE_HEADER_LEN (4 * 4) +#define XCURSOR_FILE_TOC_LEN (3 * 4) + +typedef struct _XcursorFileToc +{ + XcursorUInt type; /* chunk type */ + XcursorUInt subtype; /* subtype (size for images) */ + XcursorUInt position; /* absolute position in file */ } XcursorFileToc; -typedef struct _XcursorFileHeader { - XcursorUInt magic; /* magic number */ - XcursorUInt header; /* byte length of header */ - XcursorUInt version; /* file version number */ - XcursorUInt ntoc; /* number of toc entries */ - XcursorFileToc *tocs; /* table of contents */ +typedef struct _XcursorFileHeader +{ + XcursorUInt magic; /* magic number */ + XcursorUInt header; /* byte length of header */ + XcursorUInt version; /* file version number */ + XcursorUInt ntoc; /* number of toc entries */ + XcursorFileToc *tocs; /* table of contents */ } XcursorFileHeader; /* @@ -125,13 +125,14 @@ typedef struct _XcursorFileHeader { * CARD32 version chunk type version */ -#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) +#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) -typedef struct _XcursorChunkHeader { - XcursorUInt header; /* bytes in chunk header */ - XcursorUInt type; /* chunk type */ - XcursorUInt subtype; /* chunk subtype (size for images) */ - XcursorUInt version; /* version of this type */ +typedef struct _XcursorChunkHeader +{ + XcursorUInt header; /* bytes in chunk header */ + XcursorUInt type; /* chunk type */ + XcursorUInt subtype; /* chunk subtype (size for images) */ + XcursorUInt version; /* version of this type */ } XcursorChunkHeader; /* @@ -148,18 +149,19 @@ typedef struct _XcursorChunkHeader { * LISTofCARD8 text UTF-8 encoded text */ -#define XCURSOR_COMMENT_TYPE 0xfffe0001 -#define XCURSOR_COMMENT_VERSION 1 -#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4)) -#define XCURSOR_COMMENT_COPYRIGHT 1 -#define XCURSOR_COMMENT_LICENSE 2 -#define XCURSOR_COMMENT_OTHER 3 -#define XCURSOR_COMMENT_MAX_LEN 0x100000 - -typedef struct _XcursorComment { - XcursorUInt version; - XcursorUInt comment_type; - char *comment; +#define XCURSOR_COMMENT_TYPE 0xfffe0001 +#define XCURSOR_COMMENT_VERSION 1 +#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 * 4)) +#define XCURSOR_COMMENT_COPYRIGHT 1 +#define XCURSOR_COMMENT_LICENSE 2 +#define XCURSOR_COMMENT_OTHER 3 +#define XCURSOR_COMMENT_MAX_LEN 0x100000 + +typedef struct _XcursorComment +{ + XcursorUInt version; + XcursorUInt comment_type; + char *comment; } XcursorComment; /* @@ -178,14 +180,15 @@ typedef struct _XcursorComment { * LISTofCARD32 pixels ARGB pixels */ -#define XCURSOR_IMAGE_TYPE 0xfffd0002 -#define XCURSOR_IMAGE_VERSION 1 -#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) -#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ +#define XCURSOR_IMAGE_TYPE 0xfffd0002 +#define XCURSOR_IMAGE_VERSION 1 +#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5 * 4)) +#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ -typedef struct _XcursorComments { - int ncomment; /* number of comments */ - XcursorComment **comments; /* array of XcursorComment pointers */ +typedef struct _XcursorComments +{ + int ncomment; /* number of comments */ + XcursorComment **comments; /* array of XcursorComment pointers */ } XcursorComments; /* @@ -193,21 +196,20 @@ typedef struct _XcursorComments { */ static XcursorImage * -XcursorImageCreate (int width, int height) +XcursorImageCreate(int width, int height) { - XcursorImage *image; + XcursorImage *image; if (width < 0 || height < 0) - return NULL; + return NULL; if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; + return NULL; - image = malloc (sizeof (XcursorImage) + - width * height * sizeof (XcursorPixel)); + image = malloc(sizeof(XcursorImage) + width * height * sizeof(XcursorPixel)); if (!image) - return NULL; + return NULL; image->version = XCURSOR_IMAGE_VERSION; - image->pixels = (XcursorPixel *) (image + 1); + image->pixels = (XcursorPixel *)(image + 1); image->size = width > height ? width : height; image->width = width; image->height = height; @@ -216,325 +218,305 @@ XcursorImageCreate (int width, int height) } static void -XcursorImageDestroy (XcursorImage *image) +XcursorImageDestroy(XcursorImage *image) { - free (image); + free(image); } static XcursorImages * -XcursorImagesCreate (int size) +XcursorImagesCreate(int size) { - XcursorImages *images; + XcursorImages *images; - images = malloc (sizeof (XcursorImages) + - size * sizeof (XcursorImage *)); + images = malloc(sizeof(XcursorImages) + size * sizeof(XcursorImage *)); if (!images) - return NULL; + return NULL; images->nimage = 0; - images->images = (XcursorImage **) (images + 1); + images->images = (XcursorImage **)(images + 1); return images; } -void -XcursorImagesDestroy (XcursorImages *images) +void XcursorImagesDestroy(XcursorImages *images) { - int n; + int n; if (!images) return; for (n = 0; n < images->nimage; n++) - XcursorImageDestroy (images->images[n]); - free (images); + XcursorImageDestroy(images->images[n]); + free(images); } static XcursorBool -_XcursorReadUInt (XcursorFile *file, XcursorUInt *u) +_XcursorReadUInt(XcursorFile *file, XcursorUInt *u) { - uint8_t bytes[4]; + uint8_t bytes[4]; if (!file || !u) return XcursorFalse; - if ((*file->read) (file, bytes, 4) != 4) - return XcursorFalse; + if ((*file->read)(file, bytes, 4) != 4) + return XcursorFalse; - *u = ((XcursorUInt)(bytes[0]) << 0) | - ((XcursorUInt)(bytes[1]) << 8) | - ((XcursorUInt)(bytes[2]) << 16) | - ((XcursorUInt)(bytes[3]) << 24); + *u = ((XcursorUInt)(bytes[0]) << 0) | ((XcursorUInt)(bytes[1]) << 8) | ((XcursorUInt)(bytes[2]) << 16) | ((XcursorUInt)(bytes[3]) << 24); return XcursorTrue; } static void -_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader) +_XcursorFileHeaderDestroy(XcursorFileHeader *fileHeader) { - free (fileHeader); + free(fileHeader); } static XcursorFileHeader * -_XcursorFileHeaderCreate (XcursorUInt ntoc) +_XcursorFileHeaderCreate(XcursorUInt ntoc) { - XcursorFileHeader *fileHeader; + XcursorFileHeader *fileHeader; if (ntoc > 0x10000) - return NULL; - fileHeader = malloc (sizeof (XcursorFileHeader) + - ntoc * sizeof (XcursorFileToc)); + return NULL; + fileHeader = malloc(sizeof(XcursorFileHeader) + ntoc * sizeof(XcursorFileToc)); if (!fileHeader) - return NULL; + return NULL; fileHeader->magic = XCURSOR_MAGIC; fileHeader->header = XCURSOR_FILE_HEADER_LEN; fileHeader->version = XCURSOR_FILE_VERSION; fileHeader->ntoc = ntoc; - fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); + fileHeader->tocs = (XcursorFileToc *)(fileHeader + 1); return fileHeader; } static XcursorFileHeader * -_XcursorReadFileHeader (XcursorFile *file) +_XcursorReadFileHeader(XcursorFile *file) { - XcursorFileHeader head, *fileHeader; - XcursorUInt skip; - unsigned int n; + XcursorFileHeader head, *fileHeader; + XcursorUInt skip; + unsigned int n; if (!file) return NULL; - if (!_XcursorReadUInt (file, &head.magic)) - return NULL; + if (!_XcursorReadUInt(file, &head.magic)) + return NULL; if (head.magic != XCURSOR_MAGIC) - return NULL; - if (!_XcursorReadUInt (file, &head.header)) - return NULL; - if (!_XcursorReadUInt (file, &head.version)) - return NULL; - if (!_XcursorReadUInt (file, &head.ntoc)) - return NULL; + return NULL; + if (!_XcursorReadUInt(file, &head.header)) + return NULL; + if (!_XcursorReadUInt(file, &head.version)) + return NULL; + if (!_XcursorReadUInt(file, &head.ntoc)) + return NULL; skip = head.header - XCURSOR_FILE_HEADER_LEN; if (skip) - if (!(*file->skip) (file, skip)) - return NULL; - fileHeader = _XcursorFileHeaderCreate (head.ntoc); + if (!(*file->skip)(file, skip)) + return NULL; + fileHeader = _XcursorFileHeaderCreate(head.ntoc); if (!fileHeader) - return NULL; + return NULL; fileHeader->magic = head.magic; fileHeader->header = head.header; fileHeader->version = head.version; fileHeader->ntoc = head.ntoc; - for (n = 0; n < fileHeader->ntoc; n++) - { - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) - break; - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) - break; - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) - break; + for (n = 0; n < fileHeader->ntoc; n++) { + if (!_XcursorReadUInt(file, &fileHeader->tocs[n].type)) + break; + if (!_XcursorReadUInt(file, &fileHeader->tocs[n].subtype)) + break; + if (!_XcursorReadUInt(file, &fileHeader->tocs[n].position)) + break; } - if (n != fileHeader->ntoc) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; + if (n != fileHeader->ntoc) { + _XcursorFileHeaderDestroy(fileHeader); + return NULL; } return fileHeader; } static XcursorBool -_XcursorSeekToToc (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc) +_XcursorSeekToToc(XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc) { if (!file || !fileHeader) return XcursorFalse; - return (*file->seek) (file, fileHeader->tocs[toc].position); + return (*file->seek)(file, fileHeader->tocs[toc].position); } static XcursorBool -_XcursorFileReadChunkHeader (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc, - XcursorChunkHeader *chunkHeader) +_XcursorFileReadChunkHeader(XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc, + XcursorChunkHeader *chunkHeader) { if (!file || !fileHeader || !chunkHeader) return XcursorFalse; - if (!_XcursorSeekToToc (file, fileHeader, toc)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->header)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->type)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->subtype)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->version)) - return XcursorFalse; + if (!_XcursorSeekToToc(file, fileHeader, toc)) + return XcursorFalse; + if (!_XcursorReadUInt(file, &chunkHeader->header)) + return XcursorFalse; + if (!_XcursorReadUInt(file, &chunkHeader->type)) + return XcursorFalse; + if (!_XcursorReadUInt(file, &chunkHeader->subtype)) + return XcursorFalse; + if (!_XcursorReadUInt(file, &chunkHeader->version)) + return XcursorFalse; /* sanity check */ - if (chunkHeader->type != fileHeader->tocs[toc].type || - chunkHeader->subtype != fileHeader->tocs[toc].subtype) - return XcursorFalse; + if (chunkHeader->type != fileHeader->tocs[toc].type || chunkHeader->subtype != fileHeader->tocs[toc].subtype) + return XcursorFalse; return XcursorTrue; } -#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a)) +#define dist(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) static XcursorDim -_XcursorFindBestSize (XcursorFileHeader *fileHeader, - XcursorDim size, - int *nsizesp) +_XcursorFindBestSize(XcursorFileHeader *fileHeader, + XcursorDim size, + int *nsizesp) { unsigned int n; - int nsizes = 0; - XcursorDim bestSize = 0; - XcursorDim thisSize; + int nsizes = 0; + XcursorDim bestSize = 0; + XcursorDim thisSize; if (!fileHeader || !nsizesp) return 0; - for (n = 0; n < fileHeader->ntoc; n++) - { - if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE) - continue; - thisSize = fileHeader->tocs[n].subtype; - if (!bestSize || dist (thisSize, size) < dist (bestSize, size)) - { - bestSize = thisSize; - nsizes = 1; - } - else if (thisSize == bestSize) - nsizes++; + for (n = 0; n < fileHeader->ntoc; n++) { + if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE) + continue; + thisSize = fileHeader->tocs[n].subtype; + if (!bestSize || dist(thisSize, size) < dist(bestSize, size)) { + bestSize = thisSize; + nsizes = 1; + } else if (thisSize == bestSize) + nsizes++; } *nsizesp = nsizes; return bestSize; } static int -_XcursorFindImageToc (XcursorFileHeader *fileHeader, - XcursorDim size, - int count) +_XcursorFindImageToc(XcursorFileHeader *fileHeader, + XcursorDim size, + int count) { - unsigned int toc; - XcursorDim thisSize; + unsigned int toc; + XcursorDim thisSize; if (!fileHeader) return 0; - for (toc = 0; toc < fileHeader->ntoc; toc++) - { - if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE) - continue; - thisSize = fileHeader->tocs[toc].subtype; - if (thisSize != size) - continue; - if (!count) - break; - count--; + for (toc = 0; toc < fileHeader->ntoc; toc++) { + if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE) + continue; + thisSize = fileHeader->tocs[toc].subtype; + if (thisSize != size) + continue; + if (!count) + break; + count--; } if (toc == fileHeader->ntoc) - return -1; + return -1; return toc; } static XcursorImage * -_XcursorReadImage (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc) +_XcursorReadImage(XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc) { - XcursorChunkHeader chunkHeader; - XcursorImage head; - XcursorImage *image; - int n; - XcursorPixel *p; + XcursorChunkHeader chunkHeader; + XcursorImage head; + XcursorImage *image; + int n; + XcursorPixel *p; if (!file || !fileHeader) return NULL; - if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) - return NULL; - if (!_XcursorReadUInt (file, &head.width)) - return NULL; - if (!_XcursorReadUInt (file, &head.height)) - return NULL; - if (!_XcursorReadUInt (file, &head.xhot)) - return NULL; - if (!_XcursorReadUInt (file, &head.yhot)) - return NULL; - if (!_XcursorReadUInt (file, &head.delay)) - return NULL; + if (!_XcursorFileReadChunkHeader(file, fileHeader, toc, &chunkHeader)) + return NULL; + if (!_XcursorReadUInt(file, &head.width)) + return NULL; + if (!_XcursorReadUInt(file, &head.height)) + return NULL; + if (!_XcursorReadUInt(file, &head.xhot)) + return NULL; + if (!_XcursorReadUInt(file, &head.yhot)) + return NULL; + if (!_XcursorReadUInt(file, &head.delay)) + return NULL; /* sanity check data */ - if (head.width > XCURSOR_IMAGE_MAX_SIZE || - head.height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; + if (head.width > XCURSOR_IMAGE_MAX_SIZE || head.height > XCURSOR_IMAGE_MAX_SIZE) + return NULL; if (head.width == 0 || head.height == 0) - return NULL; + return NULL; if (head.xhot > head.width || head.yhot > head.height) - return NULL; + return NULL; /* Create the image and initialize it */ - image = XcursorImageCreate (head.width, head.height); + image = XcursorImageCreate(head.width, head.height); if (image == NULL) - return NULL; + return NULL; if (chunkHeader.version < image->version) - image->version = chunkHeader.version; + image->version = chunkHeader.version; image->size = chunkHeader.subtype; image->xhot = head.xhot; image->yhot = head.yhot; image->delay = head.delay; n = image->width * image->height; p = image->pixels; - while (n--) - { - if (!_XcursorReadUInt (file, p)) - { - XcursorImageDestroy (image); - return NULL; - } - p++; + while (n--) { + if (!_XcursorReadUInt(file, p)) { + XcursorImageDestroy(image); + return NULL; + } + p++; } return image; } XcursorImages * -XcursorXcFileLoadImages (XcursorFile *file, int size) +XcursorXcFileLoadImages(XcursorFile *file, int size) { - XcursorFileHeader *fileHeader; - XcursorDim bestSize; - int nsize; - XcursorImages *images; - int n; - int toc; + XcursorFileHeader *fileHeader; + XcursorDim bestSize; + int nsize; + XcursorImages *images; + int n; + int toc; if (!file || size < 0) - return NULL; - fileHeader = _XcursorReadFileHeader (file); + return NULL; + fileHeader = _XcursorReadFileHeader(file); if (!fileHeader) - return NULL; - bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); - if (!bestSize) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; + return NULL; + bestSize = _XcursorFindBestSize(fileHeader, (XcursorDim)size, &nsize); + if (!bestSize) { + _XcursorFileHeaderDestroy(fileHeader); + return NULL; } - images = XcursorImagesCreate (nsize); - if (!images) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; + images = XcursorImagesCreate(nsize); + if (!images) { + _XcursorFileHeaderDestroy(fileHeader); + return NULL; } - for (n = 0; n < nsize; n++) - { - toc = _XcursorFindImageToc (fileHeader, bestSize, n); - if (toc < 0) - break; - images->images[images->nimage] = _XcursorReadImage (file, fileHeader, - toc); - if (!images->images[images->nimage]) - break; - images->nimage++; + for (n = 0; n < nsize; n++) { + toc = _XcursorFindImageToc(fileHeader, bestSize, n); + if (toc < 0) + break; + images->images[images->nimage] = _XcursorReadImage(file, fileHeader, + toc); + if (!images->images[images->nimage]) + break; + images->nimage++; } - _XcursorFileHeaderDestroy (fileHeader); - if (images->nimage != nsize) - { - XcursorImagesDestroy (images); - images = NULL; + _XcursorFileHeaderDestroy(fileHeader); + if (images->nimage != nsize) { + XcursorImagesDestroy(images); + images = NULL; } return images; } diff --git a/como/input/extern/xcursor.h b/como/input/extern/xcursor.h index 4fec64e60..9d28486e9 100644 --- a/como/input/extern/xcursor.h +++ b/como/input/extern/xcursor.h @@ -35,45 +35,47 @@ extern "C" { #include -typedef int XcursorBool; -typedef uint32_t XcursorUInt; +typedef int XcursorBool; +typedef uint32_t XcursorUInt; -typedef XcursorUInt XcursorDim; -typedef XcursorUInt XcursorPixel; +typedef XcursorUInt XcursorDim; +typedef XcursorUInt XcursorPixel; -typedef struct _XcursorImage { - XcursorUInt version; /* version of the image data */ - XcursorDim size; /* nominal size for matching */ - XcursorDim width; /* actual width */ - XcursorDim height; /* actual height */ - XcursorDim xhot; /* hot spot x (must be inside image) */ - XcursorDim yhot; /* hot spot y (must be inside image) */ - XcursorUInt delay; /* animation delay to next frame (ms) */ - XcursorPixel *pixels; /* pointer to pixels */ +typedef struct _XcursorImage +{ + XcursorUInt version; /* version of the image data */ + XcursorDim size; /* nominal size for matching */ + XcursorDim width; /* actual width */ + XcursorDim height; /* actual height */ + XcursorDim xhot; /* hot spot x (must be inside image) */ + XcursorDim yhot; /* hot spot y (must be inside image) */ + XcursorUInt delay; /* animation delay to next frame (ms) */ + XcursorPixel *pixels; /* pointer to pixels */ } XcursorImage; /* * Other data structures exposed by the library API */ -typedef struct _XcursorImages { - int nimage; /* number of images */ - XcursorImage **images; /* array of XcursorImage pointers */ +typedef struct _XcursorImages +{ + int nimage; /* number of images */ + XcursorImage **images; /* array of XcursorImage pointers */ } XcursorImages; typedef struct _XcursorFile XcursorFile; -struct _XcursorFile { - void *closure; - int (*read) (XcursorFile *file, uint8_t *buf, int len); - XcursorBool (*skip) (XcursorFile *file, long offset); - XcursorBool (*seek) (XcursorFile *file, long offset); +struct _XcursorFile +{ + void *closure; + int (*read)(XcursorFile *file, uint8_t *buf, int len); + XcursorBool (*skip)(XcursorFile *file, long offset); + XcursorBool (*seek)(XcursorFile *file, long offset); }; XcursorImages * -XcursorXcFileLoadImages (XcursorFile *file, int size); +XcursorXcFileLoadImages(XcursorFile *file, int size); -void -XcursorImagesDestroy (XcursorImages *images); +void XcursorImagesDestroy(XcursorImages *images); #ifdef __cplusplus } From 09d4a8204c88df195a56f2550ce7e8553893ae0e Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 31 May 2024 14:56:10 +0300 Subject: [PATCH 06/17] feat: use "grabbing" cursor during interactive move BUG: 483305 --- como/win/move.h | 2 +- tests/integration/pointer_input.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/como/win/move.h b/como/win/move.h index f7119a143..319cc71d9 100644 --- a/como/win/move.h +++ b/como/win/move.h @@ -117,7 +117,7 @@ void update_cursor(Win* win) break; default: if (mov_res.enabled) { - shape = Qt::SizeAllCursor; + shape = Qt::ClosedHandCursor; } else { shape = Qt::ArrowCursor; } diff --git a/tests/integration/pointer_input.cpp b/tests/integration/pointer_input.cpp index 727bde908..d81e85c97 100644 --- a/tests/integration/pointer_input.cpp +++ b/tests/integration/pointer_input.cpp @@ -1659,10 +1659,10 @@ TEST_CASE("pointer input", "[input]") pointer_button_pressed(BTN_LEFT, timestamp++); QVERIFY(win::is_move(c)); - auto const sizeAllCursor = loadReferenceThemeCursor(Qt::SizeAllCursor); - QVERIFY(!sizeAllCursor.image.isNull()); - QCOMPARE(cursor()->platform_image().first, sizeAllCursor.image); - QCOMPARE(cursor()->platform_image().second, sizeAllCursor.hot_spot); + auto const closed_hand_cursor = loadReferenceThemeCursor(Qt::ClosedHandCursor); + QVERIFY(!closed_hand_cursor.image.isNull()); + QCOMPARE(cursor()->platform_image().first, closed_hand_cursor.image); + QCOMPARE(cursor()->platform_image().second, closed_hand_cursor.hot_spot); // finish moving the client keyboard_key_released(KEY_LEFTMETA, timestamp++); From 20482ff25170da4f8184d6df7be59d2908eb9180 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sun, 9 Jun 2024 08:51:55 +0300 Subject: [PATCH 07/17] feat: drop morphing popups effect The effect does not work very well for two main reasons: Some clients will make a new popup rather than move an existing one, so whether it does anything is highly unpredictable as a user. Popups can be of massively different sizes with different amounts of text. This means the text in the smaller popup gets resized which doesn't look like a natural in-between state of the two popups. This defeats the objective of looking smoother. On top of that, it's rather glitchy. This effect was purely visual, no functionality changes. BUG: 473411 BUG: 466638 BUG: 416048 BUG: 461501 BUG: 466637 --- plugins/effects/CMakeLists.txt | 1 - plugins/effects/morphingpopups/CMakeLists.txt | 5 - .../package/contents/code/main.js | 131 ------------------ .../morphingpopups/package/metadata.json | 117 ---------------- 4 files changed, 254 deletions(-) delete mode 100644 plugins/effects/morphingpopups/CMakeLists.txt delete mode 100644 plugins/effects/morphingpopups/package/contents/code/main.js delete mode 100644 plugins/effects/morphingpopups/package/metadata.json diff --git a/plugins/effects/CMakeLists.txt b/plugins/effects/CMakeLists.txt index b2c9d1c1d..e2fe3b548 100644 --- a/plugins/effects/CMakeLists.txt +++ b/plugins/effects/CMakeLists.txt @@ -89,7 +89,6 @@ add_subdirectory(logout) add_subdirectory(magiclamp) add_subdirectory(magnifier) add_subdirectory(maximize) -add_subdirectory(morphingpopups) add_subdirectory(mouseclick) add_subdirectory(mousemark) add_subdirectory(overview) diff --git a/plugins/effects/morphingpopups/CMakeLists.txt b/plugins/effects/morphingpopups/CMakeLists.txt deleted file mode 100644 index 822331cd8..000000000 --- a/plugins/effects/morphingpopups/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -# -# SPDX-License-Identifier: GPL-2.0-or-later - -kwin_add_scripted_effect(morphingpopups package) diff --git a/plugins/effects/morphingpopups/package/contents/code/main.js b/plugins/effects/morphingpopups/package/contents/code/main.js deleted file mode 100644 index b2db22b8a..000000000 --- a/plugins/effects/morphingpopups/package/contents/code/main.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - SPDX-FileCopyrightText: 2012 Martin Gräßlin - SPDX-FileCopyrightText: 2016 Marco Martin - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -"use strict"; - -var morphingEffect = { - duration: animationTime(150), - loadConfig: function () { - morphingEffect.duration = animationTime(150); - }, - - handleFrameGeometryChanged: function (window, oldGeometry) { - var newGeometry = window.geometry; - - //only do the transition for near enough tooltips, - //don't cross the whole screen: ugly - var distance = Math.abs(oldGeometry.x - newGeometry.x) + Math.abs(oldGeometry.y - newGeometry.y); - - if (distance > (newGeometry.width + newGeometry.height) * 2) { - if (window.moveAnimation) { - delete window.moveAnimation; - } - if (window.fadeAnimation) { - delete window.fadeAnimation; - } - - return; - } - - //don't resize it "too much", set as four times - if ((newGeometry.width / oldGeometry.width) > 4 || - (oldGeometry.width / newGeometry.width) > 4 || - (newGeometry.height / oldGeometry.height) > 4 || - (oldGeometry.height / newGeometry.height) > 4) { - return; - } - - window.setData(Effect.WindowForceBackgroundContrastRole, true); - window.setData(Effect.WindowForceBlurRole, true); - - var couldRetarget = false; - - if (window.moveAnimation) { - if (window.moveAnimation[0]) { - couldRetarget = retarget(window.moveAnimation[0], { - value1: newGeometry.width, - value2: newGeometry.height - }, morphingEffect.duration); - } - if (couldRetarget && window.moveAnimation[1]) { - couldRetarget = retarget(window.moveAnimation[1], { - value1: newGeometry.x + newGeometry.width/2, - value2: newGeometry.y + newGeometry.height / 2 - }, morphingEffect.duration); - } - if (!couldRetarget) { - cancel(window.moveAnimation[0]); - } - - } - - if (!couldRetarget) { - window.moveAnimation = animate({ - window: window, - duration: morphingEffect.duration, - animations: [{ - type: Effect.Size, - to: { - value1: newGeometry.width, - value2: newGeometry.height - }, - from: { - value1: oldGeometry.width, - value2: oldGeometry.height - } - }, { - type: Effect.Position, - to: { - value1: newGeometry.x + newGeometry.width / 2, - value2: newGeometry.y + newGeometry.height / 2 - }, - from: { - value1: oldGeometry.x + oldGeometry.width / 2, - value2: oldGeometry.y + oldGeometry.height / 2 - } - }] - }); - - } - - couldRetarget = false; - if (window.fadeAnimation) { - couldRetarget = retarget(window.fadeAnimation[0], 1.0, morphingEffect.duration); - } - - if (!couldRetarget) { - window.fadeAnimation = animate({ - window: window, - duration: morphingEffect.duration, - animations: [{ - type: Effect.CrossFadePrevious, - to: 1.0, - from: 0.0 - }] - }); - } - }, - - manage: function (window) { - //only tooltips and notifications - if (!window.tooltip && !window.notification && !window.criticalNotification) { - return; - } - - window.windowFrameGeometryChanged.connect(morphingEffect.handleFrameGeometryChanged); - }, - - init: function () { - effect.configChanged.connect(morphingEffect.loadConfig); - effects.windowAdded.connect(morphingEffect.manage); - - for (const window of effects.stackingOrder) { - morphingEffect.manage(window); - } - } -}; -morphingEffect.init(); diff --git a/plugins/effects/morphingpopups/package/metadata.json b/plugins/effects/morphingpopups/package/metadata.json deleted file mode 100644 index d14c8b9c2..000000000 --- a/plugins/effects/morphingpopups/package/metadata.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "KPackageStructure": "KWin/Effect", - "KPlugin": { - "Authors": [ - { - "Email": "mart@kde.org", - "Name": "Marco Martin", - "Name[ar]": "ماركو مارتن", - "Name[az]": "Marco Martin", - "Name[be]": "Marco Martin", - "Name[bg]": "Marco Martin", - "Name[ca@valencia]": "Marco Martin", - "Name[ca]": "Marco Martin", - "Name[cs]": "Marco Martin", - "Name[de]": "Marco Martin", - "Name[en_GB]": "Marco Martin", - "Name[es]": "Marco Martin", - "Name[et]": "Marco Martin", - "Name[eu]": "Marco Martin", - "Name[fi]": "Marco Martin", - "Name[fr]": "Marco Martin", - "Name[hu]": "Marco Martin", - "Name[ia]": "Marco Martin", - "Name[id]": "Marco Martin", - "Name[it]": "Marco Martin", - "Name[ja]": "Marco Martin", - "Name[ka]": "Marco Martin", - "Name[ko]": "Marco Martin", - "Name[lt]": "Marco Martin", - "Name[nl]": "Marco Martin", - "Name[nn]": "Marco Martin", - "Name[pl]": "Marco Martin", - "Name[pt]": "Marco Martin", - "Name[pt_BR]": "Marco Martin", - "Name[ro]": "Marco Martin", - "Name[ru]": "Marco Martin", - "Name[sk]": "Marco Martin", - "Name[sl]": "Marco Martin", - "Name[sv]": "Marco Martin", - "Name[ta]": "மார்கோ மார்ட்டின்", - "Name[tr]": "Marco Martin", - "Name[uk]": "Marco Martin", - "Name[vi]": "Marco Martin", - "Name[x-test]": "xxMarco Martinxx", - "Name[zh_CN]": "Marco Martin", - "Name[zh_TW]": "Marco Martin" - } - ], - "Category": "Appearance", - "Description": "Cross fade animation when Tooltips or Notifications change their geometry", - "Description[ar]": "تحريك التلاشي المتقاطع عندما يغير التلميح أو الإشعار من أبعاده", - "Description[be]": "Анімацыя згасання пры змене геаметрыі выплыўных падказак і апавяшчэнняў", - "Description[bg]": "Кръстосано преливане, когато подсказките или известията променят геометрията си", - "Description[ca@valencia]": "Animació d'esvaïment creuat quan els consells d'eines o les notificacions canvien la seua geometria", - "Description[ca]": "Animació d'esvaïment creuat quan els consells d'eines o les notificacions canvien la seva geometria", - "Description[de]": "Überblendende Animationen, wenn Kurzinfos oder Benachrichtigungen ihre Geometrie ändern", - "Description[en_GB]": "Cross fade animation when Tooltips or Notifications change their geometry", - "Description[es]": "Animación cruzada cuando las ayudas emergentes o las notificaciones cambian su geometría", - "Description[et]": "Animatsioon hääbumisega, kui kohtspikrid või märguanded muudavad geomeetriat", - "Description[eu]": "Desagertze gurutzatua tresnen argibideek edo jakinarazpenek geometria aldatzen dutenean", - "Description[fi]": "Häivytysanimaatio työkaluvihjeiden tai ilmoitusten muutettua muotoaan", - "Description[fr]": "Animation en fondu enchaîné lorsque des infobulles ou des notifications modifient leurs géométries", - "Description[ia]": "Transversa animation distingite quando Consilios o Notificationes cambia le lor geometria", - "Description[it]": "Animazione in dissolvenza quando i suggerimenti e le notifiche cambiano la loro geometria", - "Description[ja]": "ツールチップや通知ポップアップのジオメトリ変更時のクロスフェードアニメーション", - "Description[nl]": "Verwissel animatie van opkomen/vervagen wanneer tekstballonnen of meldingen hun geometrie wijzigen", - "Description[nn]": "Krysstoningsanimasjon når hjelpebobler eller varslingar endrar form", - "Description[pl]": "Efekt zmiany kształtu podpowiedzi i powiadomień przy zmianie ich geometrii", - "Description[pt]": "Animações desvanecidas quando as dicas ou notificações mudam de tamanho", - "Description[ru]": "При изменении формы всплывающих подсказок или уведомлений они плавно растягиваются или сжимаются", - "Description[sl]": "Animacija navzkrižnega preliva, ko se orodnim namigom ali obvestilom spremeni geometrija", - "Description[ta]": "கருவித்துப்புகளின் மற்றும் அறிவிப்புகளின் அளவை மாற்றும்போது அவற்றை மங்கசெய்து மாற்றும்", - "Description[tr]": "Araç ipuçları veya bildirimler boyutları değiştiğinde gösterilecek çapraz geçiş canlandırması", - "Description[uk]": "Анімація зі зміною освітленості під час зміни геометрії панелей підказок і сповіщень", - "Description[vi]": "Hiệu ứng động mờ dần khi các chú giải hay thông báo thay đổi hình dạng", - "Description[x-test]": "xxCross fade animation when Tooltips or Notifications change their geometryxx", - "Description[zh_CN]": "工具提示/通知信息框大小变化时呈现过渡动效", - "Description[zh_TW]": "當工具提示或通知變更位置時交錯淡出動畫", - "EnabledByDefault": true, - "Icon": "preferences-system-windows-effect-morphingpopups", - "Id": "morphingpopups", - "License": "GPL", - "Name": "Morphing Popups", - "Name[ar]": "المنبثقات المتحورة", - "Name[be]": "Трансфармаванне выплыўных акон", - "Name[bg]": "Променящи се изскачащи прозорци", - "Name[ca@valencia]": "Missatges emergents en metamorfosi", - "Name[ca]": "Missatges emergents en metamorfosi", - "Name[cs]": "Morfující vyskakovací okna", - "Name[de]": "Verformende Aufklappfenster", - "Name[en_GB]": "Morphing Popups", - "Name[es]": "Transformación de ventanas emergentes", - "Name[eu]": "Eraldatzen diren gainerakorrak", - "Name[fi]": "Ponnahdusikkunoiden muodonmuutos", - "Name[fr]": "Effectuer un fondu enchaîné des infobulles", - "Name[ia]": "Popups de Morphing", - "Name[it]": "Finestre a comparsa che si trasformano", - "Name[ja]": "変形するポップアップ", - "Name[ka]": "ტრანსფორმირებადი მხტუნარები", - "Name[nl]": "Morphing pop-ups", - "Name[nn]": "Formendring for sprettoppvindauge", - "Name[pl]": "Zmiennokształtne okna", - "Name[pt]": "Janelas Mutantes", - "Name[pt_BR]": "Mensagens com mudança de forma", - "Name[ru]": "Анимация преобразования всплывающих окон", - "Name[sl]": "Pogovorna okna pretvorb", - "Name[tr]": "Dönüşen Açılır Pencereler", - "Name[uk]": "Аморфні контекстні панелі", - "Name[vi]": "Ô bật lên biến dạng", - "Name[x-test]": "xxMorphing Popupsxx", - "Name[zh_CN]": "气泡大小渐变动画", - "Name[zh_TW]": "交錯彈出視窗" - }, - "X-KDE-Ordering": 60, - "X-KWin-Video-Url": "https://files.kde.org/plasma/kwin/effect-videos/morphingpopups.ogv", - "X-Plasma-API": "javascript" -} From 2be7628222fd6a908377e95bb7c59d81fe167074 Mon Sep 17 00:00:00 2001 From: Nate Graham Date: Sun, 16 Jun 2024 10:46:49 -0600 Subject: [PATCH 08/17] feat: set default shortcut This effects is off by default, which means to instruct someone how to use it for debugging purposes, you need to both tell them to enable it, and then also teach them how to assign a shortcut for it. Since it's off by default, there's no harm in setting a shortcut, which simplifies the enablement instructions. I've chosen Meta+Ctrl+Alt+P, which uses so many modifiers that it won't conflict with anything. --- plugins/effects/showpaint/showpaint.cpp | 3 ++- plugins/effects/showpaint/showpaint_config.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/effects/showpaint/showpaint.cpp b/plugins/effects/showpaint/showpaint.cpp index ef5ba751a..f001644b2 100644 --- a/plugins/effects/showpaint/showpaint.cpp +++ b/plugins/effects/showpaint/showpaint.cpp @@ -28,7 +28,8 @@ ShowPaintEffect::ShowPaintEffect() auto* toggleAction = new QAction(this); toggleAction->setObjectName(QStringLiteral("Toggle")); toggleAction->setText(i18n("Toggle Show Paint")); - effects->registerGlobalShortcutAndDefault({}, toggleAction); + effects->registerGlobalShortcutAndDefault( + QList() << (Qt::CTRL | Qt::META | Qt::ALT | Qt::Key_P), toggleAction); connect(toggleAction, &QAction::triggered, this, &ShowPaintEffect::toggle); } diff --git a/plugins/effects/showpaint/showpaint_config.cpp b/plugins/effects/showpaint/showpaint_config.cpp index 65194abbd..5f4de0316 100644 --- a/plugins/effects/showpaint/showpaint_config.cpp +++ b/plugins/effects/showpaint/showpaint_config.cpp @@ -33,8 +33,10 @@ ShowPaintEffectConfig::ShowPaintEffectConfig(QObject* parent, const KPluginMetaD QAction* toggleAction = actionCollection->addAction(QStringLiteral("Toggle")); toggleAction->setText(i18n("Toggle Show Paint")); toggleAction->setProperty("isConfigurationAction", true); - KGlobalAccel::self()->setDefaultShortcut(toggleAction, {}); - KGlobalAccel::self()->setShortcut(toggleAction, {}); + KGlobalAccel::self()->setDefaultShortcut( + toggleAction, QList() << (Qt::CTRL | Qt::META | Qt::ALT | Qt::Key_P)); + KGlobalAccel::self()->setShortcut( + toggleAction, QList() << (Qt::CTRL | Qt::META | Qt::ALT | Qt::Key_P)); m_ui.shortcutsEditor->addCollection(actionCollection); From 3c47af9d31fbee5abfd6510eca2fc5c12824c669 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Thu, 13 Jun 2024 01:41:55 +0200 Subject: [PATCH 09/17] feat: don't animate the position of windows that get hidden The target position is zero, so they just move into the top left corner, which looks weird. With this commit, they just fade away without moving --- plugins/effects/private/qml/WindowHeapDelegate.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/effects/private/qml/WindowHeapDelegate.qml b/plugins/effects/private/qml/WindowHeapDelegate.qml index b1b2620ef..5713ca25e 100644 --- a/plugins/effects/private/qml/WindowHeapDelegate.qml +++ b/plugins/effects/private/qml/WindowHeapDelegate.qml @@ -226,10 +226,10 @@ Item { name: "partial" PropertyChanges { target: thumb - x: (thumb.window.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.x : 0)) * (1 - thumb.partialActivationFactor) + cell.x * thumb.partialActivationFactor - y: (thumb.window.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.y : 0)) * (1 - thumb.partialActivationFactor) + cell.y * thumb.partialActivationFactor - width: thumb.window.width * (1 - thumb.partialActivationFactor) + cell.width * thumb.partialActivationFactor - height: thumb.window.height * (1 - thumb.partialActivationFactor) + cell.height * thumb.partialActivationFactor + x: (thumb.window.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.x : 0)) * (thumb.activeHidden ? 1 : 1 - thumb.partialActivationFactor) + (thumb.activeHidden ? 0 : cell.x * thumb.partialActivationFactor) + y: (thumb.window.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.layout.Kirigami.ScenePosition.y : 0)) * (thumb.activeHidden ? 1 : 1 - thumb.partialActivationFactor) + (thumb.activeHidden ? 0 : cell.y * thumb.partialActivationFactor) + width: thumb.window.width * (thumb.activeHidden ? 1 : 1 - thumb.partialActivationFactor) + cell.width * (thumb.activeHidden ? 0 : thumb.partialActivationFactor) + height: thumb.window.height * (thumb.activeHidden ? 1 : 1 - thumb.partialActivationFactor) + cell.height * (thumb.activeHidden ? 0 : thumb.partialActivationFactor) opacity: thumb.initialHidden ? (thumb.activeHidden ? 0 : thumb.partialActivationFactor) : (thumb.activeHidden ? 1 - thumb.partialActivationFactor : 1) From 500e0199de8b632f1837c7717c082f484dc19aba Mon Sep 17 00:00:00 2001 From: Akseli Lahtinen Date: Wed, 26 Jun 2024 16:00:54 +0000 Subject: [PATCH 10/17] feat: label text background Give label text background color to make it easier to distinct from the background. BUG:483016 --- plugins/effects/private/qml/WindowHeapDelegate.qml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/effects/private/qml/WindowHeapDelegate.qml b/plugins/effects/private/qml/WindowHeapDelegate.qml index 5713ca25e..82cbc702d 100644 --- a/plugins/effects/private/qml/WindowHeapDelegate.qml +++ b/plugins/effects/private/qml/WindowHeapDelegate.qml @@ -166,20 +166,27 @@ Item { anchors.bottom: thumbSource.bottom anchors.bottomMargin: -Math.round(height / 4) visible: !thumb.activeHidden && !activeDragHandler.active - - - PlasmaExtras.ShadowedLabel { + PC3.Label { id: caption visible: thumb.windowTitleVisible width: cell.width maximumLineCount: 1 anchors.top: parent.bottom + anchors.topMargin: Kirigami.Units.largeSpacing anchors.horizontalCenter: parent.horizontalCenter elide: Text.ElideRight text: thumb.window.caption + color: Kirigami.Theme.textColor textFormat: Text.PlainText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter + background: Rectangle { + anchors.centerIn: parent + height: parent.contentHeight + Kirigami.Units.gridUnit + width: parent.contentWidth + Kirigami.Units.gridUnit + color: Kirigami.Theme.backgroundColor + radius: Kirigami.Units.cornerRadius + } } } From 3dfcf323cca3c200193932785cf9fc3101ce8cd9 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 27 Jun 2024 16:05:17 +0300 Subject: [PATCH 11/17] fix: fix MenuButton not accepting button press events If two mouse areas are stacked on top of each other and a button press event is sent so one of them accepts it, QMouseEvent::isAccepted() will still return false. It's a QtQuick bug, see the associated upstream bug report https://bugreports.qt.io/browse/QTBUG-126733. On the other hand, given that the MenuButton implements its own input handling, we can port it away from DecorationButton to mitigate the issue. BUG: 488993 --- plugins/kdecorations/aurorae/src/qml/MenuButton.qml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/kdecorations/aurorae/src/qml/MenuButton.qml b/plugins/kdecorations/aurorae/src/qml/MenuButton.qml index 88655961d..fa2c261cb 100644 --- a/plugins/kdecorations/aurorae/src/qml/MenuButton.qml +++ b/plugins/kdecorations/aurorae/src/qml/MenuButton.qml @@ -15,10 +15,14 @@ import QtQuick import org.kde.kwin.decoration import org.kde.kirigami 2.20 as Kirigami -DecorationButton { - property bool closeOnDoubleClick: decorationSettings.closeOnDoubleClickOnMenu +Item { id: menuButton - buttonType: DecorationOptions.DecorationButtonMenu + property int buttonType: DecorationOptions.DecorationButtonMenu + property bool hovered: false + property bool pressed: false + property bool toggled: false + property bool closeOnDoubleClick: decorationSettings.closeOnDoubleClickOnMenu + Kirigami.Icon { anchors.fill: parent source: decoration.client.icon @@ -61,7 +65,7 @@ DecorationButton { } parent.pressed = false; } - onClicked: { + onClicked: (mouse) => { // for right clicks we show the menu instantly // and if the option is disabled we always show menu directly if (!menuButton.closeOnDoubleClick || mouse.button == Qt.RightButton) { From daf74481816da73c58158dcede67510755641bec Mon Sep 17 00:00:00 2001 From: Akseli Lahtinen Date: Wed, 3 Jul 2024 20:33:09 +0000 Subject: [PATCH 12/17] fix: label topMargin to small, remove height padding This should help avoiding the window heap delegaet labels drawing on top of each other in Overview effect. BUG:489595 --- plugins/effects/private/qml/WindowHeapDelegate.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/effects/private/qml/WindowHeapDelegate.qml b/plugins/effects/private/qml/WindowHeapDelegate.qml index 82cbc702d..fafdf35a0 100644 --- a/plugins/effects/private/qml/WindowHeapDelegate.qml +++ b/plugins/effects/private/qml/WindowHeapDelegate.qml @@ -172,7 +172,7 @@ Item { width: cell.width maximumLineCount: 1 anchors.top: parent.bottom - anchors.topMargin: Kirigami.Units.largeSpacing + anchors.topMargin: Kirigami.Units.smallSpacing anchors.horizontalCenter: parent.horizontalCenter elide: Text.ElideRight text: thumb.window.caption @@ -182,8 +182,8 @@ Item { verticalAlignment: Text.AlignVCenter background: Rectangle { anchors.centerIn: parent - height: parent.contentHeight + Kirigami.Units.gridUnit - width: parent.contentWidth + Kirigami.Units.gridUnit + height: parent.contentHeight + Kirigami.Units.smallSpacing + width: parent.contentWidth + Kirigami.Units.smallSpacing color: Kirigami.Theme.backgroundColor radius: Kirigami.Units.cornerRadius } From bd26870c1f8a4c0e6dcb14e556b3e39c9b0add32 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Mon, 23 Sep 2024 16:14:05 +0200 Subject: [PATCH 13/17] feat: implement input device group stub --- como/input/dbus/device.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/como/input/dbus/device.h b/como/input/dbus/device.h index 09fe19995..c18924969 100644 --- a/como/input/dbus/device.h +++ b/como/input/dbus/device.h @@ -156,6 +156,7 @@ class COMO_EXPORT device : public QObject Q_PROPERTY(bool defaultMapToWorkspace READ defaultMapToWorkspace CONSTANT) Q_PROPERTY(bool mapToWorkspace READ isMapToWorkspace WRITE setMapToWorkspace NOTIFY mapToWorkspaceChanged) + Q_PROPERTY(QString deviceGroupId READ deviceGroupId CONSTANT) bool defaultMapToWorkspace() const { @@ -171,6 +172,11 @@ class COMO_EXPORT device : public QObject { } + QString deviceGroupId() const + { + return {}; + } + public: explicit device(input::control::keyboard* control, QObject* parent); explicit device(input::control::pointer* control, QObject* parent); From 1529f61f147fcf245fcddb4a276b160d13e1ba22 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 24 Jul 2024 15:09:45 +0000 Subject: [PATCH 14/17] fix: avoid caching animation duration This is problematic as then we do not catch changes to animation speed settings, it also doesn't make the code more readable when it's only used in one place. BUG: 490703 --- plugins/effects/logout/package/contents/code/main.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/plugins/effects/logout/package/contents/code/main.js b/plugins/effects/logout/package/contents/code/main.js index db33749a3..c5ed605d2 100644 --- a/plugins/effects/logout/package/contents/code/main.js +++ b/plugins/effects/logout/package/contents/code/main.js @@ -9,12 +9,6 @@ SPDX-License-Identifier: GPL-2.0-or-later "use strict"; var logoutEffect = { - inDuration: animationTime(800), - outDuration: animationTime(400), - loadConfig: function () { - logoutEffect.inDuration = animationTime(800); - logoutEffect.outDuration = animationTime(400); - }, isLogoutWindow: function (window) { if (window.windowClass === "ksmserver-logout-greeter ksmserver-logout-greeter") { return true; @@ -32,7 +26,7 @@ var logoutEffect = { } window.inAnimation = animate({ window: window, - duration: logoutEffect.inDuration, + duration: animationTime(800), type: Effect.Opacity, from: 0.0, to: 1.0 @@ -49,14 +43,13 @@ var logoutEffect = { } window.outAnimation = animate({ window: window, - duration: logoutEffect.outDuration, + duration: animationTime(400), type: Effect.Opacity, from: 1.0, to: 0.0 }); }, init: function () { - logoutEffect.loadConfig(); effects.windowAdded.connect(logoutEffect.opened); effects.windowClosed.connect(logoutEffect.closed); } From a8cb8e35c60bd03b369c4e67cb2ce06c3842c566 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Mon, 5 Aug 2024 20:38:01 +0200 Subject: [PATCH 15/17] refactor: remove decorationInnerRect It's the same as contentsRect --- como/render/effect/interface/effect_window.h | 11 ----------- como/render/effect/window_impl.h | 5 ----- plugins/effects/backgroundcontrast/contrast.cpp | 4 ++-- plugins/effects/blur/blur.cpp | 4 ++-- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/como/render/effect/interface/effect_window.h b/como/render/effect/interface/effect_window.h index 0215c9d1d..91e57e42f 100644 --- a/como/render/effect/interface/effect_window.h +++ b/como/render/effect/interface/effect_window.h @@ -238,11 +238,6 @@ class COMO_EXPORT EffectWindow : public QObject * Geometry of the actual window contents inside the whole (including decorations) window. */ Q_PROPERTY(QRect contentsRect READ contentsRect) - /** - * Geometry of the transparent rect in the decoration. - * May be different from contentsRect if the decoration is extended into the client area. - */ - Q_PROPERTY(QRect decorationInnerRect READ decorationInnerRect) Q_PROPERTY(bool hasDecoration READ hasDecoration) Q_PROPERTY(QStringList activities READ activities) Q_PROPERTY(bool onCurrentActivity READ isOnCurrentActivity) @@ -435,12 +430,6 @@ class COMO_EXPORT EffectWindow : public QObject * Geometry of the actual window contents inside the whole (including decorations) window. */ virtual QRect contentsRect() const = 0; - /** - * Geometry of the transparent rect in the decoration. - * May be different from contentsRect() if the decoration is extended into the client area. - * @since 4.5 - */ - virtual QRect decorationInnerRect() const = 0; bool hasDecoration() const; virtual bool decorationHasAlpha() const = 0; /** diff --git a/como/render/effect/window_impl.h b/como/render/effect/window_impl.h index 02434aae1..6b48263b5 100644 --- a/como/render/effect/window_impl.h +++ b/como/render/effect/window_impl.h @@ -677,11 +677,6 @@ class effects_window_impl : public EffectWindow *window.ref_win); } - QRect decorationInnerRect() const override - { - return contentsRect(); - } - KDecoration2::Decoration* decoration() const override { return std::visit(overload{[](auto&& ref_win) { return win::decoration(ref_win); }}, diff --git a/plugins/effects/backgroundcontrast/contrast.cpp b/plugins/effects/backgroundcontrast/contrast.cpp index 274c3ecfb..78ecf320d 100644 --- a/plugins/effects/backgroundcontrast/contrast.cpp +++ b/plugins/effects/backgroundcontrast/contrast.cpp @@ -129,11 +129,11 @@ QRegion ContrastEffect::contrastRegion(const EffectWindow* w) const if (auto const it = m_windowData.find(w); it != m_windowData.end()) { auto const& appRegion = it->second.contrastRegion; if (!appRegion.isEmpty()) { - region |= appRegion.translated(w->contentsRect().topLeft()) & w->decorationInnerRect(); + region |= appRegion.translated(w->contentsRect().topLeft()) & w->contentsRect(); } else { // An empty region means that the blur effect should be enabled // for the whole window. - region = w->decorationInnerRect(); + region = w->contentsRect(); } } diff --git a/plugins/effects/blur/blur.cpp b/plugins/effects/blur/blur.cpp index bb6acab4a..3fdb765d9 100644 --- a/plugins/effects/blur/blur.cpp +++ b/plugins/effects/blur/blur.cpp @@ -293,7 +293,7 @@ QRegion BlurEffect::deco_blur_region(EffectWindow const* win) const return QRegion(); } - auto const decorationRegion = QRegion(win->decoration()->rect()) - win->decorationInnerRect(); + auto const decorationRegion = QRegion(win->decoration()->rect()) - win->contentsRect(); // We return only blurred regions that belong to decoration region. return decorationRegion.intersected(win->decoration()->blurRegion()); @@ -331,7 +331,7 @@ QRegion BlurEffect::blur_region(EffectWindow const* win) const return win->rect(); } - auto region = app_region.translated(win->contentsRect().topLeft()) & win->decorationInnerRect(); + auto region = app_region.translated(win->contentsRect().topLeft()) & win->contentsRect(); if (win->decorationHasAlpha() && deco_supports_blur_behind(win)) { region |= deco_blur_region(win); } From 76150cfc08919badf2b0f4cd0a3a95933ec97734 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 29 Feb 2024 15:54:51 +0200 Subject: [PATCH 16/17] fix: linearize desktops in the desktop bar when using non linear desktop layout Hiding the desktop bar based on the desktop layout produces unexpected results. BUG: 482023 --- plugins/effects/overview/qml/main.qml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/effects/overview/qml/main.qml b/plugins/effects/overview/qml/main.qml index 604d4ccf9..d6f0d6c1d 100644 --- a/plugins/effects/overview/qml/main.qml +++ b/plugins/effects/overview/qml/main.qml @@ -32,7 +32,6 @@ FocusScope { property bool organized: false property bool verticalDesktopBar: KWinComponents.Workspace.desktopGridHeight >= bar.desktopCount && KWinComponents.Workspace.desktopGridHeight != 1 - property bool anyDesktopBar: verticalDesktopBar || KWinComponents.Workspace.desktopGridHeight == 1 // The values of overviewVal and gridVal might not be 0 on startup, // but we always want to animate from 0 to those values. So, we initially @@ -272,7 +271,6 @@ FocusScope { Item { id: desktopBar - visible: container.anyDesktopBar // (overviewVal, gridVal) represents the state of the overview // in a 2D coordinate plane. Math.atan2 returns the angle between @@ -308,7 +306,7 @@ FocusScope { opacity: desktopBar.opacity anchors.left: container.verticalDesktopBar ? desktopBar.right : parent.left anchors.right: parent.right - anchors.top: container.verticalDesktopBar || !container.anyDesktopBar ? parent.top : desktopBar.bottom + anchors.top: container.verticalDesktopBar ? parent.top : desktopBar.bottom anchors.topMargin: Kirigami.Units.largeSpacing height: searchField.height + 1 * Kirigami.Units.largeSpacing @@ -340,7 +338,7 @@ FocusScope { // These are the minimum position of maximum size of the desktop preview in the overview property int minX: Kirigami.Units.largeSpacing + (container.verticalDesktopBar ? desktopBar.width : 0) - property int minY: Kirigami.Units.largeSpacing + topBar.height + (container.verticalDesktopBar || !container.anyDesktopBar ? 0 : desktopBar.height) + property int minY: Kirigami.Units.largeSpacing + topBar.height + (container.verticalDesktopBar ? 0 : desktopBar.height) property int maxWidth: currentGeometry.width - minX - Kirigami.Units.gridUnit * 2 property int maxHeight: currentGeometry.height - minY - Kirigami.Units.gridUnit * 2 @@ -655,7 +653,6 @@ FocusScope { partialActivationFactor: container.overviewVal + container.gridVal * effect.organizedGrid targetScale: { - if (!container.anyDesktopBar) return targetScale; if (overviewVal != 1) return targetScale; let coordinate = container.verticalDesktopBar ? 'x' : 'y' if (!activeDragHandler.active) { From 7e03e50c9c36c1e433d9a76a05cc8c1862a56c34 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 11 Sep 2024 23:16:07 +0200 Subject: [PATCH 17/17] fix: fix drag and drop hotspot The hotspot should be relative to the window item being dragged, the scale applies to both. --- plugins/effects/private/qml/WindowHeapDelegate.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/effects/private/qml/WindowHeapDelegate.qml b/plugins/effects/private/qml/WindowHeapDelegate.qml index fafdf35a0..8bbbb9c76 100644 --- a/plugins/effects/private/qml/WindowHeapDelegate.qml +++ b/plugins/effects/private/qml/WindowHeapDelegate.qml @@ -103,8 +103,8 @@ Item { Drag.supportedActions: Qt.MoveAction Drag.source: thumb.window Drag.hotSpot: Qt.point( - thumb.activeDragHandler.centroid.pressPosition.x * thumb.targetScale, - thumb.activeDragHandler.centroid.pressPosition.y * thumb.targetScale) + thumb.activeDragHandler.centroid.pressPosition.x, + thumb.activeDragHandler.centroid.pressPosition.y) Drag.keys: ["kwin-window"] onXChanged: effect.checkItemDraggedOutOfScreen(thumbSource)