mirror of
https://gitee.com/openharmony/window_window_manager
synced 2025-02-26 18:58:10 +00:00
commit
afd4689f4b
@ -38,8 +38,7 @@ public:
|
||||
DisplayId CreateVirtualDisplay(const VirtualDisplayInfo &virtualDisplayInfo,
|
||||
sptr<Surface> surface);
|
||||
bool DestroyVirtualDisplay(DisplayId displayId);
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> GetDisplaySnapshot(DisplayId displayId);
|
||||
sptr<Media::PixelMap> GetDisplaySnapshot(DisplayId displayId);
|
||||
void Clear();
|
||||
private:
|
||||
DisplayManagerAdapter() = default;
|
||||
|
@ -40,40 +40,77 @@ const sptr<Display> DisplayManager::GetDisplayById(DisplayId displayId)
|
||||
return display;
|
||||
}
|
||||
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> DisplayManager::GetScreenshot(DisplayId displayId)
|
||||
// {
|
||||
// sptr<Media::PixelMap> screenShot = SingletonContainer::Get<DisplayManagerAdapter>().GetDisplaySnapshot(displayId);
|
||||
// if (screenShot == nullptr) {
|
||||
// WLOGFE("DisplayManager::GetScreenshot failed!\n");
|
||||
// return nullptr;
|
||||
// }
|
||||
sptr<Media::PixelMap> DisplayManager::GetScreenshot(DisplayId displayId)
|
||||
{
|
||||
if (displayId == DISPLAY_ID_INVALD) {
|
||||
WLOGFE("displayId invalid!");
|
||||
return nullptr;
|
||||
}
|
||||
sptr<Media::PixelMap> screenShot = SingletonContainer::Get<DisplayManagerAdapter>().GetDisplaySnapshot(displayId);
|
||||
if (screenShot == nullptr) {
|
||||
WLOGFE("DisplayManager::GetScreenshot failed!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return screenShot;
|
||||
// }
|
||||
return screenShot;
|
||||
}
|
||||
|
||||
// sptr<Media::PixelMap> DisplayManager::GetScreenshot(DisplayId displayId, const Media::Rect &rect,
|
||||
// const Media::Size &size, int rotation)
|
||||
// {
|
||||
// sptr<Media::PixelMap> screenShot = SingletonContainer::Get<DisplayManagerAdapter>().GetDisplaySnapshot(displayId);
|
||||
// if (screenShot == nullptr) {
|
||||
// WLOGFE("DisplayManager::GetScreenshot failed!\n");
|
||||
// return nullptr;
|
||||
// }
|
||||
bool DisplayManager::CheckRectOffsetValid(int32_t param) const
|
||||
{
|
||||
if (param < 0 || param > MAX_RESOLUTION_VALUE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// // create crop dest pixelmap
|
||||
// Media::InitializationOptions opt;
|
||||
// opt.size.width = size.width;
|
||||
// opt.size.height = size.height;
|
||||
// opt.scaleMode = Media::ScaleMode::FIT_TARGET_SIZE;
|
||||
// opt.editable = false;
|
||||
// opt.useSourceIfMatch = true;
|
||||
bool DisplayManager::CheckRectSizeValid(int32_t param) const
|
||||
{
|
||||
if (param < MIN_RESOLUTION_VALUE || param > MAX_RESOLUTION_VALUE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// auto dstScreenshot = Media::PixelMap::Create(*screenShot, rect, opt);
|
||||
// sptr<Media::PixelMap> dstScreenshot_ = dstScreenshot.release();
|
||||
sptr<Media::PixelMap> DisplayManager::GetScreenshot(DisplayId displayId, const Media::Rect &rect,
|
||||
const Media::Size &size, int rotation)
|
||||
{
|
||||
if (displayId == DISPLAY_ID_INVALD) {
|
||||
WLOGFE("displayId invalid!");
|
||||
return nullptr;
|
||||
}
|
||||
if (!CheckRectOffsetValid(rect.left) || !CheckRectOffsetValid(rect.top) ||
|
||||
!CheckRectSizeValid(rect.width) || !CheckRectSizeValid(rect.height)) {
|
||||
WLOGFE("rect invalid! left %{public}d, top %{public}d, w %{public}d, h %{public}d",
|
||||
rect.left, rect.top, rect.width, rect.height);
|
||||
return nullptr;
|
||||
}
|
||||
if (!CheckRectSizeValid(size.width) || !CheckRectSizeValid(size.height)) {
|
||||
WLOGFE("size invalid! w %{public}d, h %{public}d", rect.width, rect.height);
|
||||
return nullptr;
|
||||
}
|
||||
sptr<Media::PixelMap> screenShot = SingletonContainer::Get<DisplayManagerAdapter>().GetDisplaySnapshot(displayId);
|
||||
if (screenShot == nullptr) {
|
||||
WLOGFE("DisplayManager::GetScreenshot failed!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return dstScreenshot_;
|
||||
// }
|
||||
// create crop dest pixelmap
|
||||
Media::InitializationOptions opt;
|
||||
opt.size.width = size.width;
|
||||
opt.size.height = size.height;
|
||||
opt.scaleMode = Media::ScaleMode::FIT_TARGET_SIZE;
|
||||
opt.editable = false;
|
||||
opt.useSourceIfMatch = true;
|
||||
|
||||
auto pixelMap = Media::PixelMap::Create(*screenShot, rect, opt);
|
||||
if (pixelMap == nullptr) {
|
||||
WLOGFE("Media::PixelMap::Create failed!");
|
||||
return nullptr;
|
||||
}
|
||||
sptr<Media::PixelMap> dstScreenshot = pixelMap.release();
|
||||
|
||||
return dstScreenshot;
|
||||
}
|
||||
|
||||
const sptr<Display> DisplayManager::GetDefaultDisplay()
|
||||
{
|
||||
|
@ -64,20 +64,19 @@ sptr<Display> DisplayManagerAdapter::GetDisplayById(DisplayId displayId)
|
||||
return display;
|
||||
}
|
||||
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> DisplayManagerAdapter::GetDisplaySnapshot(DisplayId displayId)
|
||||
// {
|
||||
// std::lock_guard<std::mutex> lock(mutex_);
|
||||
sptr<Media::PixelMap> DisplayManagerAdapter::GetDisplaySnapshot(DisplayId displayId)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// if (!InitDMSProxyLocked()) {
|
||||
// WLOGFE("displayManagerAdapter::GetDisplaySnapshot: InitDMSProxyLocked failed!");
|
||||
// return nullptr;
|
||||
// }
|
||||
if (!InitDMSProxyLocked()) {
|
||||
WLOGFE("displayManagerAdapter::GetDisplaySnapshot: InitDMSProxyLocked failed!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// sptr<Media::PixelMap> dispalySnapshot = displayManagerServiceProxy_->GetDispalySnapshot(displayId);
|
||||
sptr<Media::PixelMap> dispalySnapshot = displayManagerServiceProxy_->GetDispalySnapshot(displayId);
|
||||
|
||||
// return dispalySnapshot;
|
||||
// }
|
||||
return dispalySnapshot;
|
||||
}
|
||||
|
||||
DisplayId DisplayManagerAdapter::CreateVirtualDisplay(const VirtualDisplayInfo &virtualDisplayInfo,
|
||||
sptr<Surface> surface)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_MANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <pixel_map.h>
|
||||
#include <surface.h>
|
||||
|
||||
#include "abstract_display.h"
|
||||
@ -34,8 +35,7 @@ public:
|
||||
RSScreenModeInfo GetScreenActiveMode(ScreenId id);
|
||||
ScreenId CreateVirtualScreen(const VirtualDisplayInfo &virtualDisplayInfo, sptr<Surface> surface);
|
||||
bool DestroyVirtualScreen(ScreenId screenId);
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> GetScreenSnapshot(ScreenId screenId);
|
||||
sptr<Media::PixelMap> GetScreenSnapshot(ScreenId screenId);
|
||||
|
||||
private:
|
||||
AbstractDisplayManager();
|
||||
|
@ -17,13 +17,11 @@
|
||||
#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_INTERFACE_H
|
||||
|
||||
#include <iremote_broker.h>
|
||||
|
||||
#include <pixel_map.h>
|
||||
#include <surface.h>
|
||||
|
||||
#include "display_info.h"
|
||||
|
||||
#include "virtual_display_info.h"
|
||||
// #include "pixel_map.h"
|
||||
|
||||
namespace OHOS::Rosen {
|
||||
class IDisplayManager : public IRemoteBroker {
|
||||
@ -35,8 +33,7 @@ public:
|
||||
TRANS_ID_GET_DISPLAY_BY_ID,
|
||||
TRANS_ID_CREATE_VIRTUAL_DISPLAY,
|
||||
TRANS_ID_DESTROY_VIRTUAL_DISPLAY,
|
||||
// TODO: fix me
|
||||
// TRANS_ID_GET_DISPLAY_SNAPSHOT,
|
||||
TRANS_ID_GET_DISPLAY_SNAPSHOT,
|
||||
};
|
||||
|
||||
virtual DisplayId GetDefaultDisplayId() = 0;
|
||||
@ -46,8 +43,7 @@ public:
|
||||
sptr<Surface> surface) = 0;
|
||||
virtual bool DestroyVirtualDisplay(DisplayId displayId) = 0;
|
||||
|
||||
// TODO: fix me
|
||||
// virtual sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) = 0;
|
||||
virtual sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) = 0;
|
||||
};
|
||||
} // namespace OHOS::Rosen
|
||||
|
||||
|
@ -33,8 +33,7 @@ public:
|
||||
DisplayId CreateVirtualDisplay(const VirtualDisplayInfo &virtualDisplayInfo,
|
||||
sptr<Surface> surface) override;
|
||||
bool DestroyVirtualDisplay(DisplayId displayId) override;
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) override;
|
||||
sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) override;
|
||||
private:
|
||||
static inline BrokerDelegator<DisplayManagerProxy> delegator_;
|
||||
};
|
||||
|
@ -43,8 +43,7 @@ public:
|
||||
|
||||
DisplayId GetDefaultDisplayId() override;
|
||||
DisplayInfo GetDisplayInfoById(DisplayId displayId) override;
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) override;
|
||||
sptr<Media::PixelMap> GetDispalySnapshot(DisplayId displayId) override;
|
||||
private:
|
||||
DisplayManagerService();
|
||||
~DisplayManagerService() = default;
|
||||
|
@ -24,8 +24,6 @@ namespace {
|
||||
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "AbstractDisplayManager"};
|
||||
}
|
||||
|
||||
#define SCREENSHOT_GENERATOR
|
||||
|
||||
AbstractDisplayManager::AbstractDisplayManager() : rsInterface_(&(RSInterfaces::GetInstance()))
|
||||
{
|
||||
parepareRSScreenManger();
|
||||
@ -79,58 +77,14 @@ bool AbstractDisplayManager::DestroyVirtualScreen(ScreenId screenId)
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: fix me
|
||||
// #ifdef SCREENSHOT_GENERATOR
|
||||
// sptr<Media::PixelMap> TempCreatePixelMap()
|
||||
// {
|
||||
// // pixel_map testing code
|
||||
// Media::InitializationOptions opt;
|
||||
// opt.size.width = 1920;
|
||||
// opt.size.height = 1080;
|
||||
// opt.pixelFormat = Media::PixelFormat::RGBA_8888;
|
||||
// opt.alphaType = Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
|
||||
// opt.scaleMode = Media::ScaleMode::FIT_TARGET_SIZE;
|
||||
// opt.editable = false;
|
||||
// opt.useSourceIfMatch = false;
|
||||
sptr<Media::PixelMap> AbstractDisplayManager::GetScreenSnapshot(ScreenId screenId)
|
||||
{
|
||||
if (rsInterface_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// const int bitmapDepth = 8; // color depth
|
||||
// const int bpp = 4; // bytes per pixel
|
||||
// const int maxByteNum = 256;
|
||||
sptr<Media::PixelMap> screenshot = nullptr;
|
||||
|
||||
// auto data = (uint32_t *)malloc(opt.size.width * opt.size.height * bpp);
|
||||
// uint8_t *pic = (uint8_t *)data;
|
||||
// for (uint32_t i = 0; i < opt.size.width; i++) {
|
||||
// for (uint32_t j = 0; j < opt.size.height; j++) {
|
||||
// for (uint32_t k = 0; k < bpp; k++) {
|
||||
// pic[0] = rand() % maxByteNum;
|
||||
// pic++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// uint32_t colorLen = opt.size.width * opt.size.height * bpp * bitmapDepth;
|
||||
// auto newPixelMap = Media::PixelMap::Create(data, colorLen, opt);
|
||||
// sptr<Media::PixelMap> pixelMap_ = newPixelMap.release();
|
||||
// if (pixelMap_ == nullptr) {
|
||||
// WLOGFE("Failed to get pixelMap");
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// return pixelMap_;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// sptr<Media::PixelMap> AbstractDisplayManager::GetScreenSnapshot(ScreenId screenId)
|
||||
// {
|
||||
// if (rsInterface_ == nullptr) {
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// #ifdef SCREENSHOT_GENERATOR
|
||||
// sptr<Media::PixelMap> screenshot = TempCreatePixelMap();
|
||||
// #else
|
||||
// sptr<Media::PixelMap> screenshot = rsInterface_->GetScreenSnapshot(screenId);
|
||||
// #endif
|
||||
|
||||
// return screenshot;
|
||||
// }
|
||||
return screenshot;
|
||||
}
|
||||
} // namespace OHOS::Rosen
|
@ -135,38 +135,37 @@ bool DisplayManagerProxy::DestroyVirtualDisplay(DisplayId displayId)
|
||||
return reply.ReadBool();
|
||||
}
|
||||
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> DisplayManagerProxy::GetDispalySnapshot(DisplayId displayId)
|
||||
// {
|
||||
// sptr<IRemoteObject> remote = Remote();
|
||||
// if (remote == nullptr) {
|
||||
// WLOGFW("GetDispalySnapshot: remote is nullptr");
|
||||
// return nullptr;
|
||||
// }
|
||||
sptr<Media::PixelMap> DisplayManagerProxy::GetDispalySnapshot(DisplayId displayId)
|
||||
{
|
||||
sptr<IRemoteObject> remote = Remote();
|
||||
if (remote == nullptr) {
|
||||
WLOGFW("GetDispalySnapshot: remote is nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// MessageParcel data;
|
||||
// MessageParcel reply;
|
||||
// MessageOption option;
|
||||
// if (!data.WriteInterfaceToken(GetDescriptor())) {
|
||||
// WLOGFE("GetDispalySnapshot: WriteInterfaceToken failed");
|
||||
// return nullptr;
|
||||
// }
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
if (!data.WriteInterfaceToken(GetDescriptor())) {
|
||||
WLOGFE("GetDispalySnapshot: WriteInterfaceToken failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if (!data.WriteUint64(displayId)) {
|
||||
// WLOGFE("Write dispalyId failed");
|
||||
// return nullptr;
|
||||
// }
|
||||
if (!data.WriteUint64(displayId)) {
|
||||
WLOGFE("Write dispalyId failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if (remote->SendRequest(TRANS_ID_GET_DISPLAY_SNAPSHOT, data, reply, option) != ERR_NONE) {
|
||||
// WLOGFW("GetDispalySnapshot: SendRequest failed");
|
||||
// return nullptr;
|
||||
// }
|
||||
if (remote->SendRequest(TRANS_ID_GET_DISPLAY_SNAPSHOT, data, reply, option) != ERR_NONE) {
|
||||
WLOGFW("GetDispalySnapshot: SendRequest failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// sptr<Media::PixelMap> pixelMap = reply.ReadParcelable<Media::PixelMap>();
|
||||
// if (pixelMap == nullptr) {
|
||||
// WLOGFW("DisplayManagerProxy::GetDispalySnapshot SendRequest nullptr.");
|
||||
// return nullptr;
|
||||
// }
|
||||
// return pixelMap;
|
||||
// }
|
||||
sptr<Media::PixelMap> pixelMap = reply.ReadParcelable<Media::PixelMap>();
|
||||
if (pixelMap == nullptr) {
|
||||
WLOGFW("DisplayManagerProxy::GetDispalySnapshot SendRequest nullptr.");
|
||||
return nullptr;
|
||||
}
|
||||
return pixelMap;
|
||||
}
|
||||
} // namespace OHOS::Rosen
|
@ -101,13 +101,12 @@ bool DisplayManagerService::DestroyVirtualDisplay(DisplayId displayId)
|
||||
return AbstractDisplayManager::GetInstance().DestroyVirtualScreen(screenId);
|
||||
}
|
||||
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> DisplayManagerService::GetDispalySnapshot(DisplayId displayId)
|
||||
// {
|
||||
// ScreenId screenId = GetScreenIdFromDisplayId(displayId);
|
||||
// sptr<Media::PixelMap> screenSnapshot = AbstractDisplayManager::GetInstance().GetScreenSnapshot(screenId);
|
||||
// return screenSnapshot;
|
||||
// }
|
||||
sptr<Media::PixelMap> DisplayManagerService::GetDispalySnapshot(DisplayId displayId)
|
||||
{
|
||||
ScreenId screenId = GetScreenIdFromDisplayId(displayId);
|
||||
sptr<Media::PixelMap> screenSnapshot = AbstractDisplayManager::GetInstance().GetScreenSnapshot(screenId);
|
||||
return screenSnapshot;
|
||||
}
|
||||
|
||||
void DisplayManagerService::OnStop()
|
||||
{
|
||||
|
@ -62,14 +62,17 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
|
||||
reply.WriteBool(result);
|
||||
break;
|
||||
}
|
||||
// TODO: fix me
|
||||
// case TRANS_ID_GET_DISPLAY_SNAPSHOT: {
|
||||
// DisplayId displayId = data.ReadUint64();
|
||||
case TRANS_ID_GET_DISPLAY_SNAPSHOT: {
|
||||
DisplayId displayId = data.ReadUint64();
|
||||
|
||||
// sptr<Media::PixelMap> dispalySnapshot = GetDispalySnapshot(displayId);
|
||||
// reply.WriteParcelable(dispalySnapshot.GetRefPtr());
|
||||
// break;
|
||||
// }
|
||||
sptr<Media::PixelMap> dispalySnapshot = GetDispalySnapshot(displayId);
|
||||
if (dispalySnapshot == nullptr) {
|
||||
reply.WriteParcelable(nullptr);
|
||||
break;
|
||||
}
|
||||
reply.WriteParcelable(dispalySnapshot.GetRefPtr());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WLOGFW("unknown transaction code");
|
||||
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
|
||||
|
@ -9,7 +9,7 @@
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
||||
#define FOUNDATION_DM_DISPLAY_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <pixel_map.h>
|
||||
#include <surface.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "single_instance.h"
|
||||
#include "virtual_display_info.h"
|
||||
// #include "pixel_map.h"
|
||||
// #include "wm_common.h"
|
||||
|
||||
|
||||
@ -45,10 +45,16 @@ public:
|
||||
sptr<Surface> surface, DisplayId displayIdToMirror, int32_t flags);
|
||||
|
||||
bool DestroyVirtualDisplay(DisplayId displayId);
|
||||
// TODO: fix me
|
||||
// sptr<Media::PixelMap> GetScreenshot(DisplayId displayId);
|
||||
// sptr<Media::PixelMap> GetScreenshot(DisplayId displayId, const Media::Rect &rect,
|
||||
// const Media::Size &size, int rotation);
|
||||
sptr<Media::PixelMap> GetScreenshot(DisplayId displayId);
|
||||
sptr<Media::PixelMap> GetScreenshot(DisplayId displayId, const Media::Rect &rect,
|
||||
const Media::Size &size, int rotation);
|
||||
|
||||
private:
|
||||
bool CheckRectOffsetValid(int32_t param) const;
|
||||
bool CheckRectSizeValid(int32_t param) const;
|
||||
|
||||
const int32_t MAX_RESOLUTION_VALUE = 15260; // max resolution, 16K
|
||||
const int32_t MIN_RESOLUTION_VALUE = 16; // min resolution
|
||||
};
|
||||
} // namespace OHOS::Rosen
|
||||
|
||||
|
@ -86,6 +86,7 @@ ohos_shared_library("libwmutil") {
|
||||
"//foundation/graphic/standard:libsurface",
|
||||
"//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base",
|
||||
"//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client",
|
||||
"//foundation/multimedia/image_standard/interfaces/innerkits:image_native",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
@ -128,11 +129,9 @@ ohos_shared_library("libwm") {
|
||||
"//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",
|
||||
"//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk",
|
||||
"//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy",
|
||||
"//foundation/multimedia/image_standard/interfaces/innerkits:image_native",
|
||||
"//utils/native/base:utils",
|
||||
|
||||
# TODO: fix me
|
||||
# "//foundation/multimedia/image_standard/interfaces/innerkits:image_native",
|
||||
|
||||
# weston adapter
|
||||
"//foundation/windowmanager/adapter:libwmadapter",
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user