Changeset View
Changeset View
Standalone View
Standalone View
composite.cpp
Show All 14 Lines | |||||
15 | GNU General Public License for more details. | 15 | GNU General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | #include "composite.h" | 20 | #include "composite.h" | ||
21 | 21 | | |||
22 | #include "dbusinterface.h" | 22 | #include "dbusinterface.h" | ||
23 | #include "utils.h" | | |||
24 | #include <QTextStream> | | |||
25 | #include "workspace.h" | | |||
26 | #include "client.h" | 23 | #include "client.h" | ||
27 | #include "unmanaged.h" | 24 | #include "decorations/decoratedclient.h" | ||
28 | #include "deleted.h" | 25 | #include "deleted.h" | ||
29 | #include "effects.h" | 26 | #include "effects.h" | ||
30 | #include "overlaywindow.h" | 27 | #include "overlaywindow.h" | ||
28 | #include "platform.h" | ||||
31 | #include "scene.h" | 29 | #include "scene.h" | ||
32 | #include "screens.h" | 30 | #include "screens.h" | ||
33 | #include "shadow.h" | 31 | #include "shadow.h" | ||
34 | #include "useractions.h" | | |||
35 | #include "xcbutils.h" | | |||
36 | #include "platform.h" | | |||
37 | #include "shell_client.h" | 32 | #include "shell_client.h" | ||
33 | #include "useractions.h" | ||||
34 | #include "utils.h" | ||||
38 | #include "wayland_server.h" | 35 | #include "wayland_server.h" | ||
39 | #include "decorations/decoratedclient.h" | 36 | #include "workspace.h" | ||
37 | #include "unmanaged.h" | ||||
zzag: This include directive should be before line 33. | |||||
38 | #include "xcbutils.h" | ||||
40 | 39 | | |||
41 | #include <kwingltexture.h> | 40 | #include <kwingltexture.h> | ||
42 | 41 | | |||
43 | #include <KWayland/Server/surface_interface.h> | 42 | #include <KWayland/Server/surface_interface.h> | ||
44 | 43 | | |||
45 | #include <stdio.h> | | |||
46 | | ||||
47 | #include <QtConcurrentRun> | | |||
48 | #include <QFutureWatcher> | | |||
49 | #include <QMenu> | | |||
50 | #include <QTimerEvent> | | |||
51 | #include <QDateTime> | | |||
52 | #include <QOpenGLContext> | | |||
53 | #include <QQuickWindow> | | |||
54 | #include <KGlobalAccel> | 44 | #include <KGlobalAccel> | ||
55 | #include <KLocalizedString> | 45 | #include <KLocalizedString> | ||
56 | #include <KPluginLoader> | 46 | #include <KPluginLoader> | ||
57 | #include <KPluginMetaData> | 47 | #include <KPluginMetaData> | ||
58 | #include <KNotification> | 48 | #include <KNotification> | ||
59 | #include <KSelectionWatcher> | 49 | #include <KSelectionWatcher> | ||
60 | 50 | | |||
51 | #include <QDateTime> | ||||
52 | #include <QFutureWatcher> | ||||
53 | #include <QMenu> | ||||
54 | #include <QOpenGLContext> | ||||
55 | #include <QtConcurrentRun> | ||||
56 | #include <QTextStream> | ||||
57 | #include <QTimerEvent> | ||||
58 | #include <QQuickWindow> | ||||
zzag: QQuickWindow has to go before QTextStream. | |||||
59 | | ||||
61 | #include <xcb/composite.h> | 60 | #include <xcb/composite.h> | ||
62 | #include <xcb/damage.h> | 61 | #include <xcb/damage.h> | ||
63 | 62 | | |||
63 | #include <stdio.h> | ||||
zzag: stdio.h is deprecated in C++, include cstdio instead. | |||||
64 | | ||||
64 | Q_DECLARE_METATYPE(KWin::Compositor::SuspendReason) | 65 | Q_DECLARE_METATYPE(KWin::Compositor::SuspendReason) | ||
65 | 66 | | |||
66 | namespace KWin | 67 | namespace KWin | ||
67 | { | 68 | { | ||
68 | 69 | | |||
69 | extern int currentRefreshRate(); | 70 | extern int currentRefreshRate(); | ||
70 | 71 | | |||
71 | CompositorSelectionOwner::CompositorSelectionOwner(const char *selection) : KSelectionOwner(selection, connection(), rootWindow()), owning(false) | 72 | CompositorSelectionOwner::CompositorSelectionOwner(const char *selection) : KSelectionOwner(selection, connection(), rootWindow()), owning(false) | ||
▲ Show 20 Lines • Show All 841 Lines • ▼ Show 20 Line(s) | 913 | if (!hasScene()) { | |||
913 | return false; | 914 | return false; | ||
914 | } | 915 | } | ||
915 | if (!m_scene->overlayWindow()) { | 916 | if (!m_scene->overlayWindow()) { | ||
916 | return false; | 917 | return false; | ||
917 | } | 918 | } | ||
918 | return m_scene->overlayWindow()->isVisible(); | 919 | return m_scene->overlayWindow()->isVisible(); | ||
919 | } | 920 | } | ||
920 | 921 | | |||
921 | /***************************************************** | | |||
922 | * Workspace | | |||
923 | ****************************************************/ | | |||
924 | | ||||
925 | bool Workspace::compositing() const | | |||
926 | { | | |||
927 | return m_compositor && m_compositor->hasScene(); | | |||
928 | } | | |||
929 | | ||||
930 | //**************************************** | | |||
931 | // Toplevel | | |||
932 | //**************************************** | | |||
933 | | ||||
934 | bool Toplevel::setupCompositing() | | |||
935 | { | | |||
936 | if (!compositing()) | | |||
937 | return false; | | |||
938 | | ||||
939 | if (damage_handle != XCB_NONE) | | |||
940 | return false; | | |||
941 | | ||||
942 | if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) { | | |||
943 | damage_handle = xcb_generate_id(connection()); | | |||
944 | xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); | | |||
945 | } | | |||
946 | | ||||
947 | damage_region = QRegion(0, 0, width(), height()); | | |||
948 | effect_window = new EffectWindowImpl(this); | | |||
949 | | ||||
950 | Compositor::self()->scene()->addToplevel(this); | | |||
951 | | ||||
952 | return true; | | |||
953 | } | | |||
954 | | ||||
955 | void Toplevel::finishCompositing(ReleaseReason releaseReason) | | |||
956 | { | | |||
957 | if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE) | | |||
958 | return; | | |||
959 | if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data | | |||
960 | discardWindowPixmap(); | | |||
961 | delete effect_window; | | |||
962 | } | | |||
963 | | ||||
964 | if (damage_handle != XCB_NONE && | | |||
965 | releaseReason != ReleaseReason::Destroyed) { | | |||
966 | xcb_damage_destroy(connection(), damage_handle); | | |||
967 | } | | |||
968 | | ||||
969 | damage_handle = XCB_NONE; | | |||
970 | damage_region = QRegion(); | | |||
971 | repaints_region = QRegion(); | | |||
972 | effect_window = NULL; | | |||
973 | } | | |||
974 | | ||||
975 | void Toplevel::discardWindowPixmap() | | |||
976 | { | | |||
977 | addDamageFull(); | | |||
978 | if (effectWindow() != NULL && effectWindow()->sceneWindow() != NULL) | | |||
979 | effectWindow()->sceneWindow()->pixmapDiscarded(); | | |||
980 | } | | |||
981 | | ||||
982 | void Toplevel::damageNotifyEvent() | | |||
983 | { | | |||
984 | m_isDamaged = true; | | |||
985 | | ||||
986 | // Note: The rect is supposed to specify the damage extents, | | |||
987 | // but we don't know it at this point. No one who connects | | |||
988 | // to this signal uses the rect however. | | |||
989 | emit damaged(this, QRect()); | | |||
990 | } | | |||
991 | | ||||
992 | bool Toplevel::compositing() const | | |||
993 | { | | |||
994 | if (!Workspace::self()) { | | |||
995 | return false; | | |||
996 | } | | |||
997 | return Workspace::self()->compositing(); | | |||
998 | } | | |||
999 | | ||||
1000 | void Client::damageNotifyEvent() | | |||
1001 | { | | |||
1002 | if (syncRequest.isPending && isResize()) { | | |||
1003 | emit damaged(this, QRect()); | | |||
1004 | m_isDamaged = true; | | |||
1005 | return; | | |||
1006 | } | | |||
1007 | | ||||
1008 | if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead | | |||
1009 | if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now | | |||
1010 | setReadyForPainting(); | | |||
1011 | setupWindowManagementInterface(); | | |||
1012 | } | | |||
1013 | } | | |||
1014 | | ||||
1015 | Toplevel::damageNotifyEvent(); | | |||
1016 | } | | |||
1017 | | ||||
1018 | bool Toplevel::resetAndFetchDamage() | | |||
1019 | { | | |||
1020 | if (!m_isDamaged) | | |||
1021 | return false; | | |||
1022 | | ||||
1023 | if (damage_handle == XCB_NONE) { | | |||
1024 | m_isDamaged = false; | | |||
1025 | return true; | | |||
1026 | } | | |||
1027 | | ||||
1028 | xcb_connection_t *conn = connection(); | | |||
1029 | | ||||
1030 | // Create a new region and copy the damage region to it, | | |||
1031 | // resetting the damaged state. | | |||
1032 | xcb_xfixes_region_t region = xcb_generate_id(conn); | | |||
1033 | xcb_xfixes_create_region(conn, region, 0, 0); | | |||
1034 | xcb_damage_subtract(conn, damage_handle, 0, region); | | |||
1035 | | ||||
1036 | // Send a fetch-region request and destroy the region | | |||
1037 | m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region); | | |||
1038 | xcb_xfixes_destroy_region(conn, region); | | |||
1039 | | ||||
1040 | m_isDamaged = false; | | |||
1041 | m_damageReplyPending = true; | | |||
1042 | | ||||
1043 | return m_damageReplyPending; | | |||
1044 | } | | |||
1045 | | ||||
1046 | void Toplevel::getDamageRegionReply() | | |||
1047 | { | | |||
1048 | if (!m_damageReplyPending) | | |||
1049 | return; | | |||
1050 | | ||||
1051 | m_damageReplyPending = false; | | |||
1052 | | ||||
1053 | // Get the fetch-region reply | | |||
1054 | xcb_xfixes_fetch_region_reply_t *reply = | | |||
1055 | xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, 0); | | |||
1056 | | ||||
1057 | if (!reply) | | |||
1058 | return; | | |||
1059 | | ||||
1060 | // Convert the reply to a QRegion | | |||
1061 | int count = xcb_xfixes_fetch_region_rectangles_length(reply); | | |||
1062 | QRegion region; | | |||
1063 | | ||||
1064 | if (count > 1 && count < 16) { | | |||
1065 | xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply); | | |||
1066 | | ||||
1067 | QVector<QRect> qrects; | | |||
1068 | qrects.reserve(count); | | |||
1069 | | ||||
1070 | for (int i = 0; i < count; i++) | | |||
1071 | qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height); | | |||
1072 | | ||||
1073 | region.setRects(qrects.constData(), count); | | |||
1074 | } else | | |||
1075 | region += QRect(reply->extents.x, reply->extents.y, | | |||
1076 | reply->extents.width, reply->extents.height); | | |||
1077 | | ||||
1078 | damage_region += region; | | |||
1079 | repaints_region += region; | | |||
1080 | | ||||
1081 | free(reply); | | |||
1082 | } | | |||
1083 | | ||||
1084 | void Toplevel::addDamageFull() | | |||
1085 | { | | |||
1086 | if (!compositing()) | | |||
1087 | return; | | |||
1088 | | ||||
1089 | damage_region = rect(); | | |||
1090 | repaints_region |= rect(); | | |||
1091 | | ||||
1092 | emit damaged(this, rect()); | | |||
1093 | } | | |||
1094 | | ||||
1095 | void Toplevel::resetDamage() | | |||
1096 | { | | |||
1097 | damage_region = QRegion(); | | |||
1098 | } | | |||
1099 | | ||||
1100 | void Toplevel::addRepaint(const QRect& r) | | |||
1101 | { | | |||
1102 | if (!compositing()) { | | |||
1103 | return; | | |||
1104 | } | | |||
1105 | repaints_region += r; | | |||
1106 | emit needsRepaint(); | | |||
1107 | } | | |||
1108 | | ||||
1109 | void Toplevel::addRepaint(int x, int y, int w, int h) | | |||
1110 | { | | |||
1111 | QRect r(x, y, w, h); | | |||
1112 | addRepaint(r); | | |||
1113 | } | | |||
1114 | | ||||
1115 | void Toplevel::addRepaint(const QRegion& r) | | |||
1116 | { | | |||
1117 | if (!compositing()) { | | |||
1118 | return; | | |||
1119 | } | | |||
1120 | repaints_region += r; | | |||
1121 | emit needsRepaint(); | | |||
1122 | } | | |||
1123 | | ||||
1124 | void Toplevel::addLayerRepaint(const QRect& r) | | |||
1125 | { | | |||
1126 | if (!compositing()) { | | |||
1127 | return; | | |||
1128 | } | | |||
1129 | layer_repaints_region += r; | | |||
1130 | emit needsRepaint(); | | |||
1131 | } | | |||
1132 | | ||||
1133 | void Toplevel::addLayerRepaint(int x, int y, int w, int h) | | |||
1134 | { | | |||
1135 | QRect r(x, y, w, h); | | |||
1136 | addLayerRepaint(r); | | |||
1137 | } | | |||
1138 | | ||||
1139 | void Toplevel::addLayerRepaint(const QRegion& r) | | |||
1140 | { | | |||
1141 | if (!compositing()) | | |||
1142 | return; | | |||
1143 | layer_repaints_region += r; | | |||
1144 | emit needsRepaint(); | | |||
1145 | } | | |||
1146 | | ||||
1147 | void Toplevel::addRepaintFull() | | |||
1148 | { | | |||
1149 | repaints_region = visibleRect().translated(-pos()); | | |||
1150 | emit needsRepaint(); | | |||
1151 | } | | |||
1152 | | ||||
1153 | void Toplevel::resetRepaints() | | |||
1154 | { | | |||
1155 | repaints_region = QRegion(); | | |||
1156 | layer_repaints_region = QRegion(); | | |||
1157 | } | | |||
1158 | | ||||
1159 | void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h) | | |||
1160 | { | | |||
1161 | addWorkspaceRepaint(QRect(x, y, w, h)); | | |||
1162 | } | | |||
1163 | | ||||
1164 | void Toplevel::addWorkspaceRepaint(const QRect& r2) | | |||
1165 | { | | |||
1166 | if (!compositing()) | | |||
1167 | return; | | |||
1168 | Compositor::self()->addRepaint(r2); | | |||
1169 | } | | |||
1170 | | ||||
1171 | //**************************************** | | |||
1172 | // Client | | |||
1173 | //**************************************** | | |||
1174 | | ||||
1175 | bool Client::setupCompositing() | | |||
1176 | { | | |||
1177 | if (!Toplevel::setupCompositing()){ | | |||
1178 | return false; | | |||
1179 | } | | |||
1180 | updateVisibility(); // for internalKeep() | | |||
1181 | return true; | | |||
1182 | } | | |||
1183 | | ||||
1184 | void Client::finishCompositing(ReleaseReason releaseReason) | | |||
1185 | { | | |||
1186 | Toplevel::finishCompositing(releaseReason); | | |||
1187 | updateVisibility(); | | |||
1188 | // for safety in case KWin is just resizing the window | | |||
1189 | resetHaveResizeEffect(); | | |||
1190 | } | | |||
1191 | | ||||
1192 | } // namespace | 922 | } // namespace |
This include directive should be before line 33.