Commit 7a65f3e5 authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

X11 and Ozone: Move ResetWindowRegion to XWindow

This is a very X11 specific method. Thus, move it to X11 space.

Bug: 990756
Change-Id: I69ee7b59f62c3bd3f2f4fd6af5a5a3183e04743d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1834090
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702971}
parent cb5fc880
......@@ -26,6 +26,7 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_path.h"
#include "ui/platform_window/common/platform_window_defaults.h"
namespace ui {
......@@ -609,6 +610,7 @@ void XWindow::SetBounds(const gfx::Rect& requested_bounds_in_pixels) {
// (possibly synthetic) ConfigureNotify about the actual size and correct
// |bounds_in_pixels_| later.
bounds_in_pixels_ = bounds_in_pixels;
ResetWindowRegion();
}
bool XWindow::IsXWindowVisible() const {
......@@ -807,6 +809,19 @@ void XWindow::MoveCursorTo(const gfx::Point& location_in_pixels) {
bounds_in_pixels_.y() + location_in_pixels.y());
}
void XWindow::ResetWindowRegion() {
XRegion* xregion = nullptr;
if (!use_custom_shape() && !IsMaximized() && !IsFullscreen()) {
SkPath window_mask;
GetWindowMaskForXWindow(bounds().size(), &window_mask);
// Some frame views define a custom (non-rectangular) window mask. If
// so, use it to define the window shape. If not, fall through.
if (window_mask.countPoints() > 0)
xregion = gfx::CreateRegionFromSkPath(window_mask);
}
UpdateWindowRegion(xregion);
}
void XWindow::OnWorkspaceUpdated() {
auto old_workspace = workspace_;
int workspace;
......@@ -906,49 +921,13 @@ void XWindow::AfterActivationStateChanged() {
void XWindow::SetUseNativeFrame(bool use_native_frame) {
use_native_frame_ = use_native_frame;
ui::SetUseOSWindowFrame(xwindow_, use_native_frame);
ResetWindowRegion();
}
void XWindow::SetShape(_XRegion* xregion) {
void XWindow::SetShape(XRegion* xregion) {
custom_window_shape_ = !!xregion;
window_shape_.reset(xregion);
}
void XWindow::UpdateWindowRegion(_XRegion* xregion) {
// If a custom window shape was supplied then apply it.
if (use_custom_shape()) {
XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
window_shape_.get(), false);
return;
}
window_shape_.reset(xregion);
if (window_shape_) {
XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
window_shape_.get(), false);
return;
}
// If we didn't set the shape for any reason, reset the shaping information.
// How this is done depends on the border style, due to quirks and bugs in
// various window managers.
if (use_native_frame()) {
// If the window has system borders, the mask must be set to null (not a
// rectangle), because several window managers (eg, KDE, XFCE, XMonad) will
// not put borders on a window with a custom shape.
XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, x11::None,
ShapeSet);
} else {
// Conversely, if the window does not have system borders, the mask must be
// manually set to a rectangle that covers the whole window (not null). This
// is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null
// shape causes the hint to disable system borders to be ignored (resulting
// in a double border).
XRectangle r = {0, 0,
static_cast<unsigned short>(bounds_in_pixels_.width()),
static_cast<unsigned short>(bounds_in_pixels_.height())};
XShapeCombineRectangles(xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1,
ShapeSet, YXBanded);
}
ResetWindowRegion();
}
void XWindow::OnCrossingEvent(bool enter,
......@@ -1100,7 +1079,7 @@ void XWindow::ProcessEvent(XEvent* xev) {
gfx::Point window_origin = gfx::Point() + (root_point - window_point);
if (bounds_in_pixels_.origin() != window_origin) {
bounds_in_pixels_.set_origin(window_origin);
OnXWindowBoundsChanged(bounds_in_pixels_);
NotifyBoundsChanged(bounds_in_pixels_);
}
}
......@@ -1425,7 +1404,7 @@ void XWindow::OnConfigureEvent(XEvent* xev) {
if (size_changed)
DispatchResize();
else if (origin_changed)
OnXWindowBoundsChanged(bounds_in_pixels_);
NotifyBoundsChanged(bounds_in_pixels_);
}
void XWindow::SetWMSpecState(bool enabled, XAtom state1, XAtom state2) {
......@@ -1472,6 +1451,7 @@ void XWindow::UpdateWindowProperties(
is_always_on_top_ = ui::HasWMSpecProperty(
window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE"));
OnXWindowStateChanged();
ResetWindowRegion();
}
void XWindow::OnFrameExtentsUpdated() {
......@@ -1545,7 +1525,7 @@ void XWindow::DelayedResize(const gfx::Rect& bounds_in_pixels) {
SyncSetCounter(xdisplay_, extended_update_counter_,
++current_counter_value_);
}
OnXWindowBoundsChanged(bounds_in_pixels);
NotifyBoundsChanged(bounds_in_pixels);
CancelResize();
}
......@@ -1600,4 +1580,47 @@ void XWindow::SetVisualId(base::Optional<int> visual_id) {
visual_id_ = visual_id.value();
}
void XWindow::UpdateWindowRegion(XRegion* xregion) {
// If a custom window shape was supplied then apply it.
if (use_custom_shape()) {
XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
window_shape_.get(), false);
return;
}
window_shape_.reset(xregion);
if (window_shape_) {
XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
window_shape_.get(), false);
return;
}
// If we didn't set the shape for any reason, reset the shaping information.
// How this is done depends on the border style, due to quirks and bugs in
// various window managers.
if (use_native_frame()) {
// If the window has system borders, the mask must be set to null (not a
// rectangle), because several window managers (eg, KDE, XFCE, XMonad) will
// not put borders on a window with a custom shape.
XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, x11::None,
ShapeSet);
} else {
// Conversely, if the window does not have system borders, the mask must be
// manually set to a rectangle that covers the whole window (not null). This
// is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null
// shape causes the hint to disable system borders to be ignored (resulting
// in a double border).
XRectangle r = {0, 0,
static_cast<unsigned short>(bounds_in_pixels_.width()),
static_cast<unsigned short>(bounds_in_pixels_.height())};
XShapeCombineRectangles(xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1,
ShapeSet, YXBanded);
}
}
void XWindow::NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px) {
ResetWindowRegion();
OnXWindowBoundsChanged(new_bounds_in_px);
}
} // namespace ui
......@@ -23,6 +23,8 @@
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_types.h"
class SkPath;
namespace gfx {
class ImageSkia;
} // namespace gfx
......@@ -130,13 +132,15 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
void SetFlashFrameHint(bool flash_frame);
void UpdateMinAndMaxSize();
void SetUseNativeFrame(bool use_native_frame);
void SetShape(_XRegion* xregion);
void UpdateWindowRegion(_XRegion* xregion);
void SetShape(XRegion* xregion);
void DispatchResize();
void CancelResize();
void NotifySwapAfterResize();
void ConfineCursorTo(const gfx::Rect& bounds);
// Resets the window region for the current window bounds if necessary.
void ResetWindowRegion();
gfx::Rect bounds() const { return bounds_in_pixels_; }
gfx::Rect previous_bounds() const { return previous_bounds_in_pixels_; }
void set_bounds(gfx::Rect new_bounds) { bounds_in_pixels_ = new_bounds; }
......@@ -209,6 +213,10 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
void SetVisualId(base::Optional<int> visual_id);
void UpdateWindowRegion(XRegion* xregion);
void NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px);
// Interface that must be used by a class that inherits the XWindow to receive
// different messages from X Server.
virtual void OnXWindowCreated() = 0;
......@@ -228,6 +236,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0;
virtual base::Optional<gfx::Size> GetMinimumSizeForXWindow() = 0;
virtual base::Optional<gfx::Size> GetMaximumSizeForXWindow() = 0;
virtual void GetWindowMaskForXWindow(const gfx::Size& size,
SkPath* window_mask) = 0;
// The display and the native X window hosting the root window.
XDisplay* xdisplay_ = nullptr;
......@@ -334,7 +344,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
gfx::Size max_size_in_pixels_;
// The window shape if the window is non-rectangular.
gfx::XScopedPtr<_XRegion, gfx::XObjectDeleter<_XRegion, int, XDestroyRegion>>
gfx::XScopedPtr<XRegion, gfx::XObjectDeleter<XRegion, int, XDestroyRegion>>
window_shape_;
// Whether |window_shape_| was set via SetShape().
......
......@@ -150,8 +150,6 @@ jumbo_component("gfx") {
"path_mac.mm",
"path_win.cc",
"path_win.h",
"path_x11.cc",
"path_x11.h",
"platform_font.h",
"platform_font_ios.h",
"platform_font_ios.mm",
......@@ -397,8 +395,6 @@ jumbo_component("gfx") {
if (use_x11) {
deps += [ "//ui/gfx/x" ]
configs += [ "//build/config/linux:x11" ]
} else {
sources -= [ "path_x11.cc" ]
}
}
......
......@@ -19,6 +19,8 @@ jumbo_component("x") {
"x11_connection.h",
"x11_error_tracker.cc",
"x11_error_tracker.h",
"x11_path.cc",
"x11_path.h",
"x11_switches.cc",
"x11_switches.h",
"x11_types.cc",
......@@ -31,5 +33,6 @@ jumbo_component("x") {
deps = [
"//base",
"//skia",
]
}
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/path_x11.h"
#include "ui/gfx/x/x11_path.h"
#include <memory>
......@@ -28,7 +28,7 @@ Region CreateRegionFromSkRegion(const SkRegion& region) {
}
Region CreateRegionFromSkPath(const SkPath& path) {
int point_count = path.getPoints(NULL, 0);
int point_count = path.getPoints(nullptr, 0);
std::unique_ptr<SkPoint[]> points(new SkPoint[point_count]);
path.getPoints(points.get(), point_count);
std::unique_ptr<XPoint[]> x11_points(new XPoint[point_count]);
......
......@@ -2,26 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_PATH_X11_H_
#define UI_GFX_PATH_X11_H_
#ifndef UI_GFX_X_X11_PATH_H_
#define UI_GFX_X_X11_PATH_H_
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/x/x11_types.h"
class SkPath;
class SkRegion;
typedef struct _XRegion REGION;
namespace gfx {
// Creates a new REGION given |region|. The caller is responsible for destroying
// the returned region.
GFX_EXPORT REGION* CreateRegionFromSkRegion(const SkRegion& region);
// Creates a new XRegion given |region|. The caller is responsible for
// destroying the returned region.
GFX_EXPORT XRegion* CreateRegionFromSkRegion(const SkRegion& region);
// Creates a new REGION given |path|. The caller is responsible for destroying
// Creates a new XRegion given |path|. The caller is responsible for destroying
// the returned region.
GFX_EXPORT REGION* CreateRegionFromSkPath(const SkPath& path);
GFX_EXPORT XRegion* CreateRegionFromSkPath(const SkPath& path);
} // namespace gfx
#endif // UI_GFX_PATH_X11_H_
#endif // UI_GFX_X_X11_PATH_H_
......@@ -19,6 +19,7 @@ typedef union _XEvent XEvent;
typedef struct _XImage XImage;
typedef struct _XGC *GC;
typedef struct _XDisplay XDisplay;
typedef struct _XRegion XRegion;
typedef struct __GLXFBConfigRec *GLXFBConfig;
typedef XID GLXWindow;
typedef XID GLXDrawable;
......
......@@ -28,4 +28,9 @@ void PlatformWindowDelegateLinux::OnWorkspaceChanged() {
NOTIMPLEMENTED_LOG_ONCE();
}
void PlatformWindowDelegateLinux::GetWindowMask(const gfx::Size& size,
SkPath* window_mask) {
NOTIMPLEMENTED_LOG_ONCE();
}
} // namespace ui
......@@ -7,6 +7,12 @@
#include "ui/platform_window/platform_window_delegate_base.h"
class SkPath;
namespace gfx {
class Size;
}
namespace ui {
// This is an optional linux delegate interface, which should be implemented by
......@@ -32,6 +38,10 @@ class PlatformWindowDelegateLinux : public PlatformWindowDelegateBase {
// Notifies the delegate if the PlatformWindow has changed the workspace it is
// located in.
virtual void OnWorkspaceChanged();
// Returns a mask to be used to clip the window for the given
// size. This is used to create the non-rectangular window shape.
virtual void GetWindowMask(const gfx::Size& size, SkPath* window_mask);
};
} // namespace ui
......
......@@ -539,6 +539,11 @@ base::Optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() {
return platform_window_delegate_->GetMaximumSizeForWindow();
}
void X11Window::GetWindowMaskForXWindow(const gfx::Size& size,
SkPath* window_mask) {
platform_window_delegate_->GetWindowMask(size, window_mask);
}
void X11Window::DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& pointer_location_in_px) {
......
......@@ -126,6 +126,8 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow,
void OnXWindowRawKeyEvent(XEvent* xev) override;
base::Optional<gfx::Size> GetMinimumSizeForXWindow() override;
base::Optional<gfx::Size> GetMaximumSizeForXWindow() override;
void GetWindowMaskForXWindow(const gfx::Size& size,
SkPath* window_mask) override;
// WmMoveResizeHandler
void DispatchHostWindowDragMovement(
......
......@@ -237,6 +237,17 @@ void DesktopWindowTreeHostLinux::OnWorkspaceChanged() {
OnHostWorkspaceChanged();
}
void DesktopWindowTreeHostLinux::GetWindowMask(const gfx::Size& size,
SkPath* window_mask) {
DCHECK(window_mask);
Widget* widget = native_widget_delegate()->AsWidget();
if (widget->non_client_view()) {
// Some frame views define a custom (non-rectangular) window mask. If
// so, use it to define the window shape. If not, fall through.
widget->non_client_view()->GetWindowMask(size, window_mask);
}
}
// As DWTHX11 subclasses DWTHPlatform through DWTHLinux now (during transition
// period. see https://crbug.com/990756), we need to guard this factory method.
// TODO(msisov): remove this guard once DWTHX11 is finally merged into
......
......@@ -9,6 +9,8 @@
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
class SkPath;
namespace views {
class WindowEventFilterLinux;
......@@ -58,6 +60,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
// PlatformWindowDelegateLinux overrides:
void OnWorkspaceChanged() override;
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override;
// A handler for events intended for non client area.
// A posthandler for events intended for non client area. Handles events if no
......
......@@ -47,9 +47,9 @@
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/path_x11.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_path.h"
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/views_switches.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
......@@ -208,7 +208,7 @@ DesktopWindowTreeHostX11::CreateDragDropClient(
void DesktopWindowTreeHostX11::SetShape(
std::unique_ptr<Widget::ShapeRects> native_shape) {
_XRegion* xregion = nullptr;
XRegion* xregion = nullptr;
if (native_shape) {
SkRegion native_region;
for (const gfx::Rect& rect : *native_shape)
......@@ -228,7 +228,6 @@ void DesktopWindowTreeHostX11::SetShape(
}
}
GetXWindow()->SetShape(xregion);
ResetWindowRegion();
}
Widget::MoveLoopResult DesktopWindowTreeHostX11::RunMoveLoop(
......@@ -327,25 +326,6 @@ bool DesktopWindowTreeHostX11::ShouldCreateVisibilityController() const {
void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
GetXWindow()->SetUseNativeFrame(use_native_frame);
ResetWindowRegion();
}
void DesktopWindowTreeHostX11::ResetWindowRegion() {
_XRegion* xregion = nullptr;
if (!GetXWindow()->use_custom_shape() && !IsMaximized() && !IsFullscreen()) {
SkPath window_mask;
Widget* widget = native_widget_delegate()->AsWidget();
if (widget->non_client_view()) {
// Some frame views define a custom (non-rectangular) window mask. If
// so, use it to define the window shape. If not, fall through.
widget->non_client_view()->GetWindowMask(GetXWindow()->bounds().size(),
&window_mask);
if (window_mask.countPoints() > 0) {
xregion = gfx::CreateRegionFromSkPath(window_mask);
}
}
}
GetXWindow()->UpdateWindowRegion(xregion);
}
std::list<gfx::AcceleratedWidget>& DesktopWindowTreeHostX11::open_windows() {
......@@ -397,22 +377,11 @@ DesktopWindowTreeHostX11::GetKeyboardLayoutMap() {
return {};
}
void DesktopWindowTreeHostX11::OnBoundsChanged(const gfx::Rect& new_bounds) {
ResetWindowRegion();
WindowTreeHostPlatform::OnBoundsChanged(new_bounds);
}
void DesktopWindowTreeHostX11::OnClosed() {
open_windows().remove(GetAcceleratedWidget());
DesktopWindowTreeHostLinux::OnClosed();
}
void DesktopWindowTreeHostX11::OnWindowStateChanged(
ui::PlatformWindowState new_state) {
DesktopWindowTreeHostPlatform::OnWindowStateChanged(new_state);
ResetWindowRegion();
}
void DesktopWindowTreeHostX11::OnAcceleratedWidgetAvailable(
gfx::AcceleratedWidget widget) {
open_windows().push_front(widget);
......
......@@ -116,9 +116,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
// Sets whether the window's borders are provided by the window manager.
void SetUseNativeFrame(bool use_native_frame);
// Resets the window region for the current widget bounds if necessary.
void ResetWindowRegion();
// See comment for variable open_windows_.
static std::list<XID>& open_windows();
......@@ -135,9 +132,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
// DWTHX11 temporarily overrides the PlatformWindowDelegate methods instead of
// underlying DWTHPlatform and WTHPlatform. Eventually, these will be removed
// from here as we progress in https://crbug.com/990756.
void OnBoundsChanged(const gfx::Rect& new_bounds) override;
void OnClosed() override;
void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override;
void OnAcceleratedWidgetDestroyed() override;
void OnActivationChanged(bool active) override;
......
......@@ -15,9 +15,9 @@
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/path_x11.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_path.h"
#include "ui/views/test/views_interactive_ui_test_base.h"
#include "ui/views/test/x11_property_change_waiter.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment