| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/platform_window/x11/x11_window_base.h" | 5 #include "ui/platform_window/x11/x11_window_base.h" |
| 6 | 6 |
| 7 #include <X11/extensions/XInput2.h> | 7 #include <X11/extensions/XInput2.h> |
| 8 #include <X11/Xatom.h> | 8 #include <X11/Xatom.h> |
| 9 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
| 10 #include <X11/Xutil.h> | 10 #include <X11/Xutil.h> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 XID FindXEventTarget(const XEvent& xev) { | 35 XID FindXEventTarget(const XEvent& xev) { |
| 36 XID target = xev.xany.window; | 36 XID target = xev.xany.window; |
| 37 if (xev.type == GenericEvent) | 37 if (xev.type == GenericEvent) |
| 38 target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event; | 38 target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event; |
| 39 return target; | 39 return target; |
| 40 } | 40 } |
| 41 | 41 |
| 42 } // namespace | 42 } // namespace |
| 43 | 43 |
| 44 X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate) | 44 X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate, |
| 45 const gfx::Rect& bounds) |
| 45 : delegate_(delegate), | 46 : delegate_(delegate), |
| 46 xdisplay_(gfx::GetXDisplay()), | 47 xdisplay_(gfx::GetXDisplay()), |
| 47 xwindow_(None), | 48 xwindow_(None), |
| 48 xroot_window_(DefaultRootWindow(xdisplay_)), | 49 xroot_window_(DefaultRootWindow(xdisplay_)), |
| 49 atom_cache_(xdisplay_, kAtomsToCache) { | 50 atom_cache_(xdisplay_, kAtomsToCache), |
| 51 bounds_(bounds) { |
| 50 DCHECK(delegate_); | 52 DCHECK(delegate_); |
| 51 TouchFactory::SetTouchDeviceListFromCommandLine(); | 53 TouchFactory::SetTouchDeviceListFromCommandLine(); |
| 52 } | 54 } |
| 53 | 55 |
| 54 X11WindowBase::~X11WindowBase() { | 56 X11WindowBase::~X11WindowBase() { |
| 55 Destroy(); | 57 Destroy(); |
| 56 } | 58 } |
| 57 | 59 |
| 58 void X11WindowBase::Destroy() { | 60 void X11WindowBase::Destroy() { |
| 59 if (xwindow_ == None) | 61 if (xwindow_ == None) |
| 60 return; | 62 return; |
| 61 | 63 |
| 62 // Stop processing events. | 64 // Stop processing events. |
| 63 XID xwindow = xwindow_; | 65 XID xwindow = xwindow_; |
| 64 XDisplay* xdisplay = xdisplay_; | 66 XDisplay* xdisplay = xdisplay_; |
| 65 xwindow_ = None; | 67 xwindow_ = None; |
| 66 delegate_->OnClosed(); | 68 delegate_->OnClosed(); |
| 67 // |this| might be deleted because of the above call. | 69 // |this| might be deleted because of the above call. |
| 68 | 70 |
| 69 XDestroyWindow(xdisplay, xwindow); | 71 XDestroyWindow(xdisplay, xwindow); |
| 70 } | 72 } |
| 71 | 73 |
| 72 void X11WindowBase::Create() { | 74 void X11WindowBase::Create() { |
| 75 DCHECK(!bounds_.size().IsEmpty()); |
| 76 |
| 73 XSetWindowAttributes swa; | 77 XSetWindowAttributes swa; |
| 74 memset(&swa, 0, sizeof(swa)); | 78 memset(&swa, 0, sizeof(swa)); |
| 75 swa.background_pixmap = None; | 79 swa.background_pixmap = None; |
| 76 swa.bit_gravity = NorthWestGravity; | 80 swa.bit_gravity = NorthWestGravity; |
| 77 swa.override_redirect = g_override_redirect; | 81 swa.override_redirect = g_override_redirect; |
| 78 xwindow_ = XCreateWindow( | 82 xwindow_ = |
| 79 xdisplay_, xroot_window_, requested_bounds_.x(), requested_bounds_.y(), | 83 XCreateWindow(xdisplay_, xroot_window_, bounds_.x(), bounds_.y(), |
| 80 requested_bounds_.width(), requested_bounds_.height(), | 84 bounds_.width(), bounds_.height(), |
| 81 0, // border width | 85 0, // border width |
| 82 CopyFromParent, // depth | 86 CopyFromParent, // depth |
| 83 InputOutput, | 87 InputOutput, |
| 84 CopyFromParent, // visual | 88 CopyFromParent, // visual |
| 85 CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa); | 89 CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa); |
| 86 | 90 |
| 87 // Setup XInput event mask. | 91 // Setup XInput event mask. |
| 88 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 92 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
| 89 KeyPressMask | KeyReleaseMask | EnterWindowMask | | 93 KeyPressMask | KeyReleaseMask | EnterWindowMask | |
| 90 LeaveWindowMask | ExposureMask | VisibilityChangeMask | | 94 LeaveWindowMask | ExposureMask | VisibilityChangeMask | |
| 91 StructureNotifyMask | PropertyChangeMask | | 95 StructureNotifyMask | PropertyChangeMask | |
| 92 PointerMotionMask; | 96 PointerMotionMask; |
| 93 xwindow_events_.reset(new ui::XScopedEventSelector(xwindow_, event_mask)); | 97 xwindow_events_.reset(new ui::XScopedEventSelector(xwindow_, event_mask)); |
| 94 | 98 |
| 95 // Setup XInput2 event mask. | 99 // Setup XInput2 event mask. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 static_assert(sizeof(long) >= sizeof(pid_t), | 132 static_assert(sizeof(long) >= sizeof(pid_t), |
| 129 "pid_t should not be larger than long"); | 133 "pid_t should not be larger than long"); |
| 130 long pid = getpid(); | 134 long pid = getpid(); |
| 131 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_PID"), | 135 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_PID"), |
| 132 XA_CARDINAL, 32, PropModeReplace, | 136 XA_CARDINAL, 32, PropModeReplace, |
| 133 reinterpret_cast<unsigned char*>(&pid), 1); | 137 reinterpret_cast<unsigned char*>(&pid), 1); |
| 134 // Before we map the window, set size hints. Otherwise, some window managers | 138 // Before we map the window, set size hints. Otherwise, some window managers |
| 135 // will ignore toplevel XMoveWindow commands. | 139 // will ignore toplevel XMoveWindow commands. |
| 136 XSizeHints size_hints; | 140 XSizeHints size_hints; |
| 137 size_hints.flags = PPosition | PWinGravity; | 141 size_hints.flags = PPosition | PWinGravity; |
| 138 size_hints.x = requested_bounds_.x(); | 142 size_hints.x = bounds_.x(); |
| 139 size_hints.y = requested_bounds_.y(); | 143 size_hints.y = bounds_.y(); |
| 140 // Set StaticGravity so that the window position is not affected by the | 144 // Set StaticGravity so that the window position is not affected by the |
| 141 // frame width when running with window manager. | 145 // frame width when running with window manager. |
| 142 size_hints.win_gravity = StaticGravity; | 146 size_hints.win_gravity = StaticGravity; |
| 143 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); | 147 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); |
| 144 | 148 |
| 145 // TODO(sky): provide real scale factor. | 149 // TODO(sky): provide real scale factor. |
| 146 delegate_->OnAcceleratedWidgetAvailable(xwindow_, 1.f); | 150 delegate_->OnAcceleratedWidgetAvailable(xwindow_, 1.f); |
| 147 } | 151 } |
| 148 | 152 |
| 149 void X11WindowBase::Show() { | 153 void X11WindowBase::Show() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 167 return; | 171 return; |
| 168 XWithdrawWindow(xdisplay_, xwindow_, 0); | 172 XWithdrawWindow(xdisplay_, xwindow_, 0); |
| 169 window_mapped_ = false; | 173 window_mapped_ = false; |
| 170 } | 174 } |
| 171 | 175 |
| 172 void X11WindowBase::Close() { | 176 void X11WindowBase::Close() { |
| 173 Destroy(); | 177 Destroy(); |
| 174 } | 178 } |
| 175 | 179 |
| 176 void X11WindowBase::SetBounds(const gfx::Rect& bounds) { | 180 void X11WindowBase::SetBounds(const gfx::Rect& bounds) { |
| 177 requested_bounds_ = bounds; | 181 if (bounds == bounds_) |
| 178 if (!window_mapped_ || bounds == confirmed_bounds_) | |
| 179 return; | 182 return; |
| 180 XWindowChanges changes = {0}; | 183 |
| 181 unsigned value_mask = CWX | CWY | CWWidth | CWHeight; | 184 if (window_mapped_) { |
| 182 changes.x = bounds.x(); | 185 XWindowChanges changes = {0}; |
| 183 changes.y = bounds.y(); | 186 unsigned value_mask = CWX | CWY | CWWidth | CWHeight; |
| 184 changes.width = bounds.width(); | 187 changes.x = bounds.x(); |
| 185 changes.height = bounds.height(); | 188 changes.y = bounds.y(); |
| 186 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); | 189 changes.width = bounds.width(); |
| 190 changes.height = bounds.height(); |
| 191 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); |
| 192 } |
| 193 |
| 194 // Assume that the resize will go through as requested, which should be the |
| 195 // case if we're running without a window manager. If there's a window |
| 196 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| 197 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 198 // |bounds_| later. |
| 199 bounds_ = bounds; |
| 200 delegate_->OnBoundsChanged(bounds_); |
| 187 } | 201 } |
| 188 | 202 |
| 189 gfx::Rect X11WindowBase::GetBounds() { | 203 gfx::Rect X11WindowBase::GetBounds() { |
| 190 return confirmed_bounds_; | 204 return bounds_; |
| 191 } | 205 } |
| 192 | 206 |
| 193 void X11WindowBase::SetTitle(const base::string16& title) { | 207 void X11WindowBase::SetTitle(const base::string16& title) { |
| 194 if (window_title_ == title) | 208 if (window_title_ == title) |
| 195 return; | 209 return; |
| 196 window_title_ = title; | 210 window_title_ = title; |
| 197 std::string utf8str = base::UTF16ToUTF8(title); | 211 std::string utf8str = base::UTF16ToUTF8(title); |
| 198 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_NAME"), | 212 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_NAME"), |
| 199 atom_cache_.GetAtom("UTF8_STRING"), 8, PropModeReplace, | 213 atom_cache_.GetAtom("UTF8_STRING"), 8, PropModeReplace, |
| 200 reinterpret_cast<const unsigned char*>(utf8str.c_str()), | 214 reinterpret_cast<const unsigned char*>(utf8str.c_str()), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 215 void X11WindowBase::ToggleFullscreen() {} | 229 void X11WindowBase::ToggleFullscreen() {} |
| 216 | 230 |
| 217 void X11WindowBase::Maximize() {} | 231 void X11WindowBase::Maximize() {} |
| 218 | 232 |
| 219 void X11WindowBase::Minimize() {} | 233 void X11WindowBase::Minimize() {} |
| 220 | 234 |
| 221 void X11WindowBase::Restore() {} | 235 void X11WindowBase::Restore() {} |
| 222 | 236 |
| 223 void X11WindowBase::MoveCursorTo(const gfx::Point& location) { | 237 void X11WindowBase::MoveCursorTo(const gfx::Point& location) { |
| 224 XWarpPointer(xdisplay_, None, xroot_window_, 0, 0, 0, 0, | 238 XWarpPointer(xdisplay_, None, xroot_window_, 0, 0, 0, 0, |
| 225 confirmed_bounds_.x() + location.x(), | 239 bounds_.x() + location.x(), bounds_.y() + location.y()); |
| 226 confirmed_bounds_.y() + location.y()); | |
| 227 } | 240 } |
| 228 | 241 |
| 229 void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {} | 242 void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {} |
| 230 | 243 |
| 231 PlatformImeController* X11WindowBase::GetPlatformImeController() { | 244 PlatformImeController* X11WindowBase::GetPlatformImeController() { |
| 232 return nullptr; | 245 return nullptr; |
| 233 } | 246 } |
| 234 | 247 |
| 235 bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const { | 248 bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const { |
| 236 return xwindow_ != None && FindXEventTarget(xev) == xwindow_; | 249 return xwindow_ != None && FindXEventTarget(xev) == xwindow_; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 259 int translated_x_in_pixels = xev->xconfigure.x; | 272 int translated_x_in_pixels = xev->xconfigure.x; |
| 260 int translated_y_in_pixels = xev->xconfigure.y; | 273 int translated_y_in_pixels = xev->xconfigure.y; |
| 261 if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) { | 274 if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) { |
| 262 Window unused; | 275 Window unused; |
| 263 XTranslateCoordinates(xdisplay_, xwindow_, xroot_window_, 0, 0, | 276 XTranslateCoordinates(xdisplay_, xwindow_, xroot_window_, 0, 0, |
| 264 &translated_x_in_pixels, &translated_y_in_pixels, | 277 &translated_x_in_pixels, &translated_y_in_pixels, |
| 265 &unused); | 278 &unused); |
| 266 } | 279 } |
| 267 gfx::Rect bounds(translated_x_in_pixels, translated_y_in_pixels, | 280 gfx::Rect bounds(translated_x_in_pixels, translated_y_in_pixels, |
| 268 xev->xconfigure.width, xev->xconfigure.height); | 281 xev->xconfigure.width, xev->xconfigure.height); |
| 269 if (confirmed_bounds_ != bounds) { | 282 if (bounds_ != bounds) { |
| 270 confirmed_bounds_ = bounds; | 283 bounds_ = bounds; |
| 271 delegate_->OnBoundsChanged(confirmed_bounds_); | 284 delegate_->OnBoundsChanged(bounds_); |
| 272 } | 285 } |
| 273 break; | 286 break; |
| 274 } | 287 } |
| 275 | 288 |
| 276 case ClientMessage: { | 289 case ClientMessage: { |
| 277 Atom message = static_cast<Atom>(xev->xclient.data.l[0]); | 290 Atom message = static_cast<Atom>(xev->xclient.data.l[0]); |
| 278 if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { | 291 if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { |
| 279 delegate_->OnCloseRequest(); | 292 delegate_->OnCloseRequest(); |
| 280 } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) { | 293 } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) { |
| 281 XEvent reply_event = *xev; | 294 XEvent reply_event = *xev; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 292 } | 305 } |
| 293 | 306 |
| 294 namespace test { | 307 namespace test { |
| 295 | 308 |
| 296 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 309 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
| 297 g_override_redirect = override_redirect; | 310 g_override_redirect = override_redirect; |
| 298 } | 311 } |
| 299 | 312 |
| 300 } // namespace test | 313 } // namespace test |
| 301 } // namespace ui | 314 } // namespace ui |
| OLD | NEW |