OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "views/widget/widget.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/message_loop.h" | |
9 #include "base/utf_string_conversions.h" | |
10 #include "ui/base/hit_test.h" | |
11 #include "ui/base/l10n/l10n_font_util.h" | |
12 #include "ui/base/resource/resource_bundle.h" | |
13 #include "ui/gfx/compositor/compositor.h" | |
14 #include "ui/gfx/compositor/layer.h" | |
15 #include "ui/gfx/screen.h" | |
16 #include "ui/views/focus/focus_manager.h" | |
17 #include "ui/views/focus/focus_manager_factory.h" | |
18 #include "ui/views/focus/view_storage.h" | |
19 #include "ui/views/focus/widget_focus_manager.h" | |
20 #include "ui/views/ime/input_method.h" | |
21 #include "ui/views/window/custom_frame_view.h" | |
22 #include "views/controls/menu/menu_controller.h" | |
23 #include "views/views_delegate.h" | |
24 #include "views/widget/default_theme_provider.h" | |
25 #include "views/widget/native_widget_private.h" | |
26 #include "views/widget/root_view.h" | |
27 #include "views/widget/tooltip_manager.h" | |
28 #include "views/widget/widget_delegate.h" | |
29 | |
30 namespace { | |
31 | |
32 // Set to true if a pure Views implementation is preferred | |
33 bool use_pure_views = false; | |
34 | |
35 // True to enable debug paint that indicates where to be painted. | |
36 bool debug_paint = false; | |
37 | |
38 } // namespace | |
39 | |
40 namespace views { | |
41 | |
42 // This class is used to keep track of the event a Widget is processing, and | |
43 // restore any previously active event afterwards. | |
44 class ScopedEvent { | |
45 public: | |
46 ScopedEvent(Widget* widget, const Event& event) | |
47 : widget_(widget), | |
48 event_(&event) { | |
49 widget->event_stack_.push(this); | |
50 } | |
51 | |
52 ~ScopedEvent() { | |
53 if (widget_) | |
54 widget_->event_stack_.pop(); | |
55 } | |
56 | |
57 void reset() { | |
58 widget_ = NULL; | |
59 } | |
60 | |
61 const Event* event() { | |
62 return event_; | |
63 } | |
64 | |
65 private: | |
66 Widget* widget_; | |
67 const Event* event_; | |
68 | |
69 DISALLOW_COPY_AND_ASSIGN(ScopedEvent); | |
70 }; | |
71 | |
72 // A default implementation of WidgetDelegate, used by Widget when no | |
73 // WidgetDelegate is supplied. | |
74 class DefaultWidgetDelegate : public WidgetDelegate { | |
75 public: | |
76 DefaultWidgetDelegate(Widget* widget, const Widget::InitParams& params) | |
77 : widget_(widget), | |
78 can_activate_(!params.child && | |
79 params.type != Widget::InitParams::TYPE_POPUP) { | |
80 } | |
81 virtual ~DefaultWidgetDelegate() {} | |
82 | |
83 // Overridden from WidgetDelegate: | |
84 virtual void DeleteDelegate() OVERRIDE { | |
85 delete this; | |
86 } | |
87 virtual Widget* GetWidget() { | |
88 return widget_; | |
89 } | |
90 virtual const Widget* GetWidget() const { | |
91 return widget_; | |
92 } | |
93 | |
94 virtual bool CanActivate() const { | |
95 return can_activate_; | |
96 } | |
97 | |
98 private: | |
99 Widget* widget_; | |
100 bool can_activate_; | |
101 | |
102 DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate); | |
103 }; | |
104 | |
105 //////////////////////////////////////////////////////////////////////////////// | |
106 // Widget, InitParams: | |
107 | |
108 Widget::InitParams::InitParams() | |
109 : type(TYPE_WINDOW), | |
110 delegate(NULL), | |
111 child(false), | |
112 transient(false), | |
113 transparent(false), | |
114 accept_events(true), | |
115 can_activate(true), | |
116 keep_on_top(false), | |
117 ownership(NATIVE_WIDGET_OWNS_WIDGET), | |
118 mirror_origin_in_rtl(false), | |
119 has_dropshadow(false), | |
120 show_state(ui::SHOW_STATE_DEFAULT), | |
121 double_buffer(false), | |
122 parent(NULL), | |
123 parent_widget(NULL), | |
124 native_widget(NULL), | |
125 top_level(false), | |
126 create_texture_for_layer(true) { | |
127 } | |
128 | |
129 Widget::InitParams::InitParams(Type type) | |
130 : type(type), | |
131 delegate(NULL), | |
132 child(type == TYPE_CONTROL), | |
133 transient(type == TYPE_BUBBLE || type == TYPE_POPUP || type == TYPE_MENU), | |
134 transparent(false), | |
135 accept_events(true), | |
136 can_activate(type != TYPE_POPUP && type != TYPE_MENU), | |
137 keep_on_top(type == TYPE_MENU), | |
138 ownership(NATIVE_WIDGET_OWNS_WIDGET), | |
139 mirror_origin_in_rtl(false), | |
140 has_dropshadow(false), | |
141 show_state(ui::SHOW_STATE_DEFAULT), | |
142 double_buffer(false), | |
143 parent(NULL), | |
144 parent_widget(NULL), | |
145 native_widget(NULL), | |
146 top_level(false), | |
147 create_texture_for_layer(true) { | |
148 } | |
149 | |
150 gfx::NativeView Widget::InitParams::GetParent() const { | |
151 return parent_widget ? parent_widget->GetNativeView() : parent; | |
152 } | |
153 | |
154 //////////////////////////////////////////////////////////////////////////////// | |
155 // Widget, public: | |
156 | |
157 Widget::Widget() | |
158 : native_widget_(NULL), | |
159 widget_delegate_(NULL), | |
160 non_client_view_(NULL), | |
161 dragged_view_(NULL), | |
162 event_stack_(), | |
163 ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET), | |
164 is_secondary_widget_(true), | |
165 frame_type_(FRAME_TYPE_DEFAULT), | |
166 disable_inactive_rendering_(false), | |
167 widget_closed_(false), | |
168 saved_show_state_(ui::SHOW_STATE_DEFAULT), | |
169 focus_on_creation_(true), | |
170 is_top_level_(false), | |
171 native_widget_initialized_(false), | |
172 is_mouse_button_pressed_(false), | |
173 last_mouse_event_was_move_(false) { | |
174 } | |
175 | |
176 Widget::~Widget() { | |
177 while (!event_stack_.empty()) { | |
178 event_stack_.top()->reset(); | |
179 event_stack_.pop(); | |
180 } | |
181 | |
182 DestroyRootView(); | |
183 if (ownership_ == InitParams::WIDGET_OWNS_NATIVE_WIDGET) | |
184 delete native_widget_; | |
185 } | |
186 | |
187 // static | |
188 Widget* Widget::CreateWindow(WidgetDelegate* delegate) { | |
189 return CreateWindowWithParentAndBounds(delegate, NULL, gfx::Rect()); | |
190 } | |
191 | |
192 // static | |
193 Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate, | |
194 gfx::NativeWindow parent) { | |
195 return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect()); | |
196 } | |
197 | |
198 // static | |
199 Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate, | |
200 const gfx::Rect& bounds) { | |
201 return CreateWindowWithParentAndBounds(delegate, NULL, bounds); | |
202 } | |
203 | |
204 // static | |
205 Widget* Widget::CreateWindowWithParentAndBounds(WidgetDelegate* delegate, | |
206 gfx::NativeWindow parent, | |
207 const gfx::Rect& bounds) { | |
208 Widget* widget = new Widget; | |
209 Widget::InitParams params; | |
210 params.delegate = delegate; | |
211 #if defined(OS_WIN) || defined(USE_AURA) | |
212 params.parent = parent; | |
213 #endif | |
214 params.bounds = bounds; | |
215 widget->Init(params); | |
216 return widget; | |
217 } | |
218 | |
219 // static | |
220 void Widget::SetPureViews(bool pure) { | |
221 use_pure_views = pure; | |
222 } | |
223 | |
224 // static | |
225 bool Widget::IsPureViews() { | |
226 #if defined(USE_AURA) || defined(TOUCH_UI) | |
227 return true; | |
228 #else | |
229 return use_pure_views; | |
230 #endif | |
231 } | |
232 | |
233 // static | |
234 Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { | |
235 internal::NativeWidgetPrivate* native_widget = | |
236 internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view); | |
237 return native_widget ? native_widget->GetWidget() : NULL; | |
238 } | |
239 | |
240 // static | |
241 Widget* Widget::GetWidgetForNativeWindow(gfx::NativeWindow native_window) { | |
242 internal::NativeWidgetPrivate* native_widget = | |
243 internal::NativeWidgetPrivate::GetNativeWidgetForNativeWindow( | |
244 native_window); | |
245 return native_widget ? native_widget->GetWidget() : NULL; | |
246 } | |
247 | |
248 // static | |
249 Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) { | |
250 internal::NativeWidgetPrivate* native_widget = | |
251 internal::NativeWidgetPrivate::GetTopLevelNativeWidget(native_view); | |
252 return native_widget ? native_widget->GetWidget() : NULL; | |
253 } | |
254 | |
255 | |
256 // static | |
257 void Widget::GetAllChildWidgets(gfx::NativeView native_view, | |
258 Widgets* children) { | |
259 internal::NativeWidgetPrivate::GetAllChildWidgets(native_view, children); | |
260 } | |
261 | |
262 // static | |
263 void Widget::ReparentNativeView(gfx::NativeView native_view, | |
264 gfx::NativeView new_parent) { | |
265 internal::NativeWidgetPrivate::ReparentNativeView(native_view, new_parent); | |
266 } | |
267 | |
268 // static | |
269 int Widget::GetLocalizedContentsWidth(int col_resource_id) { | |
270 return ui::GetLocalizedContentsWidthForFont(col_resource_id, | |
271 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); | |
272 } | |
273 | |
274 // static | |
275 int Widget::GetLocalizedContentsHeight(int row_resource_id) { | |
276 return ui::GetLocalizedContentsHeightForFont(row_resource_id, | |
277 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); | |
278 } | |
279 | |
280 // static | |
281 gfx::Size Widget::GetLocalizedContentsSize(int col_resource_id, | |
282 int row_resource_id) { | |
283 return gfx::Size(GetLocalizedContentsWidth(col_resource_id), | |
284 GetLocalizedContentsHeight(row_resource_id)); | |
285 } | |
286 | |
287 // static | |
288 void Widget::SetDebugPaintEnabled(bool enabled) { | |
289 debug_paint = enabled; | |
290 } | |
291 | |
292 // static | |
293 bool Widget::IsDebugPaintEnabled() { | |
294 return debug_paint; | |
295 } | |
296 | |
297 // static | |
298 bool Widget::RequiresNonClientView(InitParams::Type type) { | |
299 return type == InitParams::TYPE_WINDOW || type == InitParams::TYPE_BUBBLE; | |
300 } | |
301 | |
302 void Widget::Init(const InitParams& params) { | |
303 is_top_level_ = params.top_level || | |
304 (!params.child && | |
305 params.type != InitParams::TYPE_CONTROL && | |
306 params.type != InitParams::TYPE_TOOLTIP); | |
307 widget_delegate_ = params.delegate ? | |
308 params.delegate : new DefaultWidgetDelegate(this, params); | |
309 ownership_ = params.ownership; | |
310 native_widget_ = params.native_widget ? | |
311 params.native_widget->AsNativeWidgetPrivate() : | |
312 internal::NativeWidgetPrivate::CreateNativeWidget(this); | |
313 GetRootView(); | |
314 default_theme_provider_.reset(new DefaultThemeProvider); | |
315 if (params.type == InitParams::TYPE_MENU) { | |
316 is_mouse_button_pressed_ = | |
317 internal::NativeWidgetPrivate::IsMouseButtonDown(); | |
318 } | |
319 native_widget_->InitNativeWidget(params); | |
320 if (RequiresNonClientView(params.type)) { | |
321 non_client_view_ = new NonClientView; | |
322 non_client_view_->SetFrameView(CreateNonClientFrameView()); | |
323 // Create the ClientView, add it to the NonClientView and add the | |
324 // NonClientView to the RootView. This will cause everything to be parented. | |
325 non_client_view_->set_client_view(widget_delegate_->CreateClientView(this)); | |
326 SetContentsView(non_client_view_); | |
327 SetInitialBounds(params.bounds); | |
328 if (params.show_state == ui::SHOW_STATE_MAXIMIZED) | |
329 Maximize(); | |
330 else if (params.show_state == ui::SHOW_STATE_MINIMIZED) | |
331 Minimize(); | |
332 UpdateWindowTitle(); | |
333 } | |
334 native_widget_initialized_ = true; | |
335 } | |
336 | |
337 // Unconverted methods (see header) -------------------------------------------- | |
338 | |
339 gfx::NativeView Widget::GetNativeView() const { | |
340 return native_widget_->GetNativeView(); | |
341 } | |
342 | |
343 gfx::NativeWindow Widget::GetNativeWindow() const { | |
344 return native_widget_->GetNativeWindow(); | |
345 } | |
346 | |
347 void Widget::AddObserver(Widget::Observer* observer) { | |
348 observers_.AddObserver(observer); | |
349 } | |
350 | |
351 void Widget::RemoveObserver(Widget::Observer* observer) { | |
352 observers_.RemoveObserver(observer); | |
353 } | |
354 | |
355 bool Widget::HasObserver(Widget::Observer* observer) { | |
356 return observers_.HasObserver(observer); | |
357 } | |
358 | |
359 bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { | |
360 return false; | |
361 } | |
362 | |
363 void Widget::ViewHierarchyChanged(bool is_add, View* parent, View* child) { | |
364 if (!is_add) { | |
365 if (child == dragged_view_) | |
366 dragged_view_ = NULL; | |
367 | |
368 FocusManager* focus_manager = GetFocusManager(); | |
369 if (focus_manager) | |
370 focus_manager->ViewRemoved(child); | |
371 ViewStorage::GetInstance()->ViewRemoved(child); | |
372 native_widget_->ViewRemoved(child); | |
373 } | |
374 } | |
375 | |
376 void Widget::NotifyNativeViewHierarchyChanged(bool attached, | |
377 gfx::NativeView native_view) { | |
378 if (!attached) { | |
379 FocusManager* focus_manager = GetFocusManager(); | |
380 // We are being removed from a window hierarchy. Treat this as | |
381 // the root_view_ being removed. | |
382 if (focus_manager) | |
383 focus_manager->ViewRemoved(root_view_.get()); | |
384 } | |
385 root_view_->NotifyNativeViewHierarchyChanged(attached, native_view); | |
386 } | |
387 | |
388 // Converted methods (see header) ---------------------------------------------- | |
389 | |
390 Widget* Widget::GetTopLevelWidget() { | |
391 return const_cast<Widget*>( | |
392 static_cast<const Widget*>(this)->GetTopLevelWidget()); | |
393 } | |
394 | |
395 const Widget* Widget::GetTopLevelWidget() const { | |
396 // GetTopLevelNativeWidget doesn't work during destruction because | |
397 // property is gone after gobject gets deleted. Short circuit here | |
398 // for toplevel so that InputMethod can remove itself from | |
399 // focus manager. | |
400 return is_top_level() ? this : native_widget_->GetTopLevelWidget(); | |
401 } | |
402 | |
403 void Widget::SetContentsView(View* view) { | |
404 root_view_->SetContentsView(view); | |
405 if (non_client_view_ != view) | |
406 non_client_view_ = NULL; | |
407 } | |
408 | |
409 View* Widget::GetContentsView() { | |
410 return root_view_->GetContentsView(); | |
411 } | |
412 | |
413 gfx::Rect Widget::GetWindowScreenBounds() const { | |
414 return native_widget_->GetWindowScreenBounds(); | |
415 } | |
416 | |
417 gfx::Rect Widget::GetClientAreaScreenBounds() const { | |
418 return native_widget_->GetClientAreaScreenBounds(); | |
419 } | |
420 | |
421 gfx::Rect Widget::GetRestoredBounds() const { | |
422 return native_widget_->GetRestoredBounds(); | |
423 } | |
424 | |
425 void Widget::SetBounds(const gfx::Rect& bounds) { | |
426 native_widget_->SetBounds(bounds); | |
427 } | |
428 | |
429 void Widget::SetSize(const gfx::Size& size) { | |
430 native_widget_->SetSize(size); | |
431 } | |
432 | |
433 void Widget::SetBoundsConstrained(const gfx::Rect& bounds) { | |
434 gfx::Rect work_area = | |
435 gfx::Screen::GetMonitorWorkAreaNearestPoint(bounds.origin()); | |
436 if (work_area.IsEmpty()) { | |
437 SetBounds(bounds); | |
438 } else { | |
439 // Inset the work area slightly. | |
440 work_area.Inset(10, 10, 10, 10); | |
441 SetBounds(work_area.AdjustToFit(bounds)); | |
442 } | |
443 } | |
444 | |
445 void Widget::MoveAboveWidget(Widget* widget) { | |
446 native_widget_->MoveAbove(widget->GetNativeView()); | |
447 } | |
448 | |
449 void Widget::MoveAbove(gfx::NativeView native_view) { | |
450 native_widget_->MoveAbove(native_view); | |
451 } | |
452 | |
453 void Widget::MoveToTop() { | |
454 native_widget_->MoveToTop(); | |
455 } | |
456 | |
457 void Widget::SetShape(gfx::NativeRegion shape) { | |
458 native_widget_->SetShape(shape); | |
459 } | |
460 | |
461 void Widget::Close() { | |
462 if (widget_closed_) { | |
463 // It appears we can hit this code path if you close a modal dialog then | |
464 // close the last browser before the destructor is hit, which triggers | |
465 // invoking Close again. | |
466 return; | |
467 } | |
468 | |
469 bool can_close = true; | |
470 if (non_client_view_) | |
471 can_close = non_client_view_->CanClose(); | |
472 if (can_close) { | |
473 SaveWindowPlacement(); | |
474 | |
475 // During tear-down the top-level focus manager becomes unavailable to | |
476 // GTK tabbed panes and their children, so normal deregistration via | |
477 // |FormManager::ViewRemoved()| calls are fouled. We clear focus here | |
478 // to avoid these redundant steps and to avoid accessing deleted views | |
479 // that may have been in focus. | |
480 if (is_top_level() && focus_manager_.get()) | |
481 focus_manager_->SetFocusedView(NULL); | |
482 | |
483 native_widget_->Close(); | |
484 widget_closed_ = true; | |
485 } | |
486 } | |
487 | |
488 void Widget::CloseNow() { | |
489 native_widget_->CloseNow(); | |
490 } | |
491 | |
492 void Widget::EnableClose(bool enable) { | |
493 if (non_client_view_) | |
494 non_client_view_->EnableClose(enable); | |
495 native_widget_->EnableClose(enable); | |
496 } | |
497 | |
498 void Widget::Show() { | |
499 if (non_client_view_) { | |
500 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && | |
501 !initial_restored_bounds_.IsEmpty()) { | |
502 native_widget_->ShowMaximizedWithBounds(initial_restored_bounds_); | |
503 } else { | |
504 native_widget_->ShowWithWindowState(saved_show_state_); | |
505 } | |
506 // |saved_show_state_| only applies the first time the window is shown. | |
507 // If we don't reset the value the window may be shown maximized every time | |
508 // it is subsequently shown after being hidden. | |
509 saved_show_state_ = ui::SHOW_STATE_NORMAL; | |
510 } else { | |
511 native_widget_->Show(); | |
512 } | |
513 } | |
514 | |
515 void Widget::Hide() { | |
516 native_widget_->Hide(); | |
517 } | |
518 | |
519 void Widget::ShowInactive() { | |
520 // If this gets called with saved_show_state_ == ui::SHOW_STATE_MAXIMIZED, | |
521 // call SetBounds()with the restored bounds to set the correct size. This | |
522 // normally should not happen, but if it does we should avoid showing unsized | |
523 // windows. | |
524 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && | |
525 !initial_restored_bounds_.IsEmpty()) { | |
526 SetBounds(initial_restored_bounds_); | |
527 saved_show_state_ = ui::SHOW_STATE_NORMAL; | |
528 } | |
529 native_widget_->ShowWithWindowState(ui::SHOW_STATE_INACTIVE); | |
530 } | |
531 | |
532 void Widget::Activate() { | |
533 native_widget_->Activate(); | |
534 } | |
535 | |
536 void Widget::Deactivate() { | |
537 native_widget_->Deactivate(); | |
538 } | |
539 | |
540 bool Widget::IsActive() const { | |
541 return native_widget_->IsActive(); | |
542 } | |
543 | |
544 void Widget::DisableInactiveRendering() { | |
545 SetInactiveRenderingDisabled(true); | |
546 } | |
547 | |
548 void Widget::SetAlwaysOnTop(bool on_top) { | |
549 native_widget_->SetAlwaysOnTop(on_top); | |
550 } | |
551 | |
552 void Widget::Maximize() { | |
553 native_widget_->Maximize(); | |
554 } | |
555 | |
556 void Widget::Minimize() { | |
557 native_widget_->Minimize(); | |
558 } | |
559 | |
560 void Widget::Restore() { | |
561 native_widget_->Restore(); | |
562 } | |
563 | |
564 bool Widget::IsMaximized() const { | |
565 return native_widget_->IsMaximized(); | |
566 } | |
567 | |
568 bool Widget::IsMinimized() const { | |
569 return native_widget_->IsMinimized(); | |
570 } | |
571 | |
572 void Widget::SetFullscreen(bool fullscreen) { | |
573 native_widget_->SetFullscreen(fullscreen); | |
574 } | |
575 | |
576 bool Widget::IsFullscreen() const { | |
577 return native_widget_->IsFullscreen(); | |
578 } | |
579 | |
580 void Widget::SetOpacity(unsigned char opacity) { | |
581 native_widget_->SetOpacity(opacity); | |
582 } | |
583 | |
584 void Widget::SetUseDragFrame(bool use_drag_frame) { | |
585 native_widget_->SetUseDragFrame(use_drag_frame); | |
586 } | |
587 | |
588 View* Widget::GetRootView() { | |
589 if (!root_view_.get()) { | |
590 // First time the root view is being asked for, create it now. | |
591 root_view_.reset(CreateRootView()); | |
592 } | |
593 return root_view_.get(); | |
594 } | |
595 | |
596 const View* Widget::GetRootView() const { | |
597 return root_view_.get(); | |
598 } | |
599 | |
600 bool Widget::IsVisible() const { | |
601 return native_widget_->IsVisible(); | |
602 } | |
603 | |
604 bool Widget::IsAccessibleWidget() const { | |
605 return native_widget_->IsAccessibleWidget(); | |
606 } | |
607 | |
608 ThemeProvider* Widget::GetThemeProvider() const { | |
609 const Widget* root_widget = GetTopLevelWidget(); | |
610 if (root_widget && root_widget != this) { | |
611 // Attempt to get the theme provider, and fall back to the default theme | |
612 // provider if not found. | |
613 ThemeProvider* provider = root_widget->GetThemeProvider(); | |
614 if (provider) | |
615 return provider; | |
616 | |
617 provider = root_widget->default_theme_provider_.get(); | |
618 if (provider) | |
619 return provider; | |
620 } | |
621 return default_theme_provider_.get(); | |
622 } | |
623 | |
624 FocusManager* Widget::GetFocusManager() { | |
625 Widget* toplevel_widget = GetTopLevelWidget(); | |
626 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; | |
627 } | |
628 | |
629 const FocusManager* Widget::GetFocusManager() const { | |
630 const Widget* toplevel_widget = GetTopLevelWidget(); | |
631 return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; | |
632 } | |
633 | |
634 InputMethod* Widget::GetInputMethod() { | |
635 if (is_top_level()) { | |
636 if (!input_method_.get()) | |
637 input_method_.reset(native_widget_->CreateInputMethod()); | |
638 return input_method_.get(); | |
639 } else { | |
640 Widget* toplevel = GetTopLevelWidget(); | |
641 // If GetTopLevelWidget() returns itself which is not toplevel, | |
642 // the widget is detached from toplevel widget. | |
643 // TODO(oshima): Fix GetTopLevelWidget() to return NULL | |
644 // if there is no toplevel. We probably need to add GetTopMostWidget() | |
645 // to replace some use cases. | |
646 return (toplevel && toplevel != this) ? toplevel->GetInputMethod() : NULL; | |
647 } | |
648 } | |
649 | |
650 void Widget::RunShellDrag(View* view, const ui::OSExchangeData& data, | |
651 int operation) { | |
652 dragged_view_ = view; | |
653 native_widget_->RunShellDrag(view, data, operation); | |
654 // If the view is removed during the drag operation, dragged_view_ is set to | |
655 // NULL. | |
656 if (view && dragged_view_ == view) { | |
657 dragged_view_ = NULL; | |
658 view->OnDragDone(); | |
659 } | |
660 } | |
661 | |
662 void Widget::SchedulePaintInRect(const gfx::Rect& rect) { | |
663 native_widget_->SchedulePaintInRect(rect); | |
664 } | |
665 | |
666 void Widget::SetCursor(gfx::NativeCursor cursor) { | |
667 native_widget_->SetCursor(cursor); | |
668 } | |
669 | |
670 void Widget::ResetLastMouseMoveFlag() { | |
671 last_mouse_event_was_move_ = false; | |
672 } | |
673 | |
674 void Widget::SetNativeWindowProperty(const char* name, void* value) { | |
675 native_widget_->SetNativeWindowProperty(name, value); | |
676 } | |
677 | |
678 void* Widget::GetNativeWindowProperty(const char* name) const { | |
679 return native_widget_->GetNativeWindowProperty(name); | |
680 } | |
681 | |
682 void Widget::UpdateWindowTitle() { | |
683 if (!non_client_view_) | |
684 return; | |
685 | |
686 // If the non-client view is rendering its own title, it'll need to relayout | |
687 // now. | |
688 non_client_view_->Layout(); | |
689 | |
690 // Update the native frame's text. We do this regardless of whether or not | |
691 // the native frame is being used, since this also updates the taskbar, etc. | |
692 string16 window_title; | |
693 if (native_widget_->IsScreenReaderActive()) { | |
694 window_title = widget_delegate_->GetAccessibleWindowTitle(); | |
695 } else { | |
696 window_title = widget_delegate_->GetWindowTitle(); | |
697 } | |
698 base::i18n::AdjustStringForLocaleDirection(&window_title); | |
699 native_widget_->SetWindowTitle(window_title); | |
700 } | |
701 | |
702 void Widget::UpdateWindowIcon() { | |
703 if (non_client_view_) | |
704 non_client_view_->UpdateWindowIcon(); | |
705 native_widget_->SetWindowIcons(widget_delegate_->GetWindowIcon(), | |
706 widget_delegate_->GetWindowAppIcon()); | |
707 } | |
708 | |
709 FocusTraversable* Widget::GetFocusTraversable() { | |
710 return static_cast<internal::RootView*>(root_view_.get()); | |
711 } | |
712 | |
713 void Widget::ThemeChanged() { | |
714 root_view_->ThemeChanged(); | |
715 } | |
716 | |
717 void Widget::LocaleChanged() { | |
718 root_view_->LocaleChanged(); | |
719 } | |
720 | |
721 void Widget::SetFocusTraversableParent(FocusTraversable* parent) { | |
722 root_view_->SetFocusTraversableParent(parent); | |
723 } | |
724 | |
725 void Widget::SetFocusTraversableParentView(View* parent_view) { | |
726 root_view_->SetFocusTraversableParentView(parent_view); | |
727 } | |
728 | |
729 void Widget::ClearNativeFocus() { | |
730 native_widget_->ClearNativeFocus(); | |
731 } | |
732 | |
733 void Widget::FocusNativeView(gfx::NativeView native_view) { | |
734 native_widget_->FocusNativeView(native_view); | |
735 } | |
736 | |
737 void Widget::UpdateFrameAfterFrameChange() { | |
738 native_widget_->UpdateFrameAfterFrameChange(); | |
739 } | |
740 | |
741 NonClientFrameView* Widget::CreateNonClientFrameView() { | |
742 NonClientFrameView* frame_view = widget_delegate_->CreateNonClientFrameView(); | |
743 if (!frame_view) | |
744 frame_view = native_widget_->CreateNonClientFrameView(); | |
745 return frame_view ? frame_view : new CustomFrameView(this); | |
746 } | |
747 | |
748 bool Widget::ShouldUseNativeFrame() const { | |
749 if (frame_type_ != FRAME_TYPE_DEFAULT) | |
750 return frame_type_ == FRAME_TYPE_FORCE_NATIVE; | |
751 return native_widget_->ShouldUseNativeFrame(); | |
752 } | |
753 | |
754 void Widget::DebugToggleFrameType() { | |
755 if (frame_type_ == FRAME_TYPE_DEFAULT) { | |
756 frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM : | |
757 FRAME_TYPE_FORCE_NATIVE; | |
758 } else { | |
759 frame_type_ = frame_type_ == FRAME_TYPE_FORCE_CUSTOM ? | |
760 FRAME_TYPE_FORCE_NATIVE : FRAME_TYPE_FORCE_CUSTOM; | |
761 } | |
762 FrameTypeChanged(); | |
763 } | |
764 | |
765 void Widget::FrameTypeChanged() { | |
766 native_widget_->FrameTypeChanged(); | |
767 } | |
768 | |
769 const ui::Compositor* Widget::GetCompositor() const { | |
770 return native_widget_->GetCompositor(); | |
771 } | |
772 | |
773 ui::Compositor* Widget::GetCompositor() { | |
774 return native_widget_->GetCompositor(); | |
775 } | |
776 | |
777 void Widget::CalculateOffsetToAncestorWithLayer(gfx::Point* offset, | |
778 ui::Layer** layer_parent) { | |
779 native_widget_->CalculateOffsetToAncestorWithLayer(offset, layer_parent); | |
780 } | |
781 | |
782 void Widget::ReorderLayers() { | |
783 native_widget_->ReorderLayers(); | |
784 } | |
785 | |
786 void Widget::NotifyAccessibilityEvent( | |
787 View* view, | |
788 ui::AccessibilityTypes::Event event_type, | |
789 bool send_native_event) { | |
790 // Send the notification to the delegate. | |
791 if (ViewsDelegate::views_delegate) | |
792 ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type); | |
793 | |
794 if (send_native_event) | |
795 native_widget_->SendNativeAccessibilityEvent(view, event_type); | |
796 } | |
797 | |
798 const NativeWidget* Widget::native_widget() const { | |
799 return native_widget_; | |
800 } | |
801 | |
802 NativeWidget* Widget::native_widget() { | |
803 return native_widget_; | |
804 } | |
805 | |
806 const Event* Widget::GetCurrentEvent() { | |
807 return event_stack_.empty() ? NULL : event_stack_.top()->event(); | |
808 } | |
809 | |
810 void Widget::TooltipTextChanged(View* view) { | |
811 TooltipManager* manager = native_widget_private()->GetTooltipManager(); | |
812 if (manager) | |
813 manager->TooltipTextChanged(view); | |
814 } | |
815 | |
816 bool Widget::SetInitialFocus() { | |
817 if (!focus_on_creation_) | |
818 return true; | |
819 View* v = widget_delegate_->GetInitiallyFocusedView(); | |
820 if (v) | |
821 v->RequestFocus(); | |
822 return !!v; | |
823 } | |
824 | |
825 bool Widget::ConvertPointFromAncestor( | |
826 const Widget* ancestor, gfx::Point* point) const { | |
827 return native_widget_->ConvertPointFromAncestor(ancestor, point); | |
828 } | |
829 | |
830 View* Widget::GetChildViewParent() { | |
831 return GetContentsView() ? GetContentsView() : GetRootView(); | |
832 } | |
833 | |
834 gfx::Rect Widget::GetWorkAreaBoundsInScreen() const { | |
835 return native_widget_->GetWorkAreaBoundsInScreen(); | |
836 } | |
837 | |
838 //////////////////////////////////////////////////////////////////////////////// | |
839 // Widget, NativeWidgetDelegate implementation: | |
840 | |
841 bool Widget::IsModal() const { | |
842 return widget_delegate_->IsModal(); | |
843 } | |
844 | |
845 bool Widget::IsDialogBox() const { | |
846 return !!widget_delegate_->AsDialogDelegate(); | |
847 } | |
848 | |
849 bool Widget::CanActivate() const { | |
850 return widget_delegate_->CanActivate(); | |
851 } | |
852 | |
853 bool Widget::IsInactiveRenderingDisabled() const { | |
854 return disable_inactive_rendering_; | |
855 } | |
856 | |
857 void Widget::EnableInactiveRendering() { | |
858 SetInactiveRenderingDisabled(false); | |
859 } | |
860 | |
861 void Widget::OnNativeWidgetActivationChanged(bool active) { | |
862 if (!active) { | |
863 SaveWindowPlacement(); | |
864 | |
865 // Close any open menus. | |
866 MenuController* menu_controller = MenuController::GetActiveInstance(); | |
867 if (menu_controller) | |
868 menu_controller->OnWidgetActivationChanged(); | |
869 } | |
870 | |
871 FOR_EACH_OBSERVER(Observer, observers_, | |
872 OnWidgetActivationChanged(this, active)); | |
873 } | |
874 | |
875 void Widget::OnNativeFocus(gfx::NativeView focused_view) { | |
876 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(focused_view, | |
877 GetNativeView()); | |
878 } | |
879 | |
880 void Widget::OnNativeBlur(gfx::NativeView focused_view) { | |
881 WidgetFocusManager::GetInstance()->OnWidgetFocusEvent(GetNativeView(), | |
882 focused_view); | |
883 } | |
884 | |
885 void Widget::OnNativeWidgetVisibilityChanged(bool visible) { | |
886 View* root = GetRootView(); | |
887 root->PropagateVisibilityNotifications(root, visible); | |
888 FOR_EACH_OBSERVER(Observer, observers_, | |
889 OnWidgetVisibilityChanged(this, visible)); | |
890 if (GetCompositor() && root->layer()) | |
891 root->layer()->SetVisible(visible); | |
892 } | |
893 | |
894 void Widget::OnNativeWidgetCreated() { | |
895 if (is_top_level()) | |
896 focus_manager_.reset(FocusManagerFactory::Create(this)); | |
897 | |
898 native_widget_->SetAccessibleRole( | |
899 widget_delegate_->GetAccessibleWindowRole()); | |
900 native_widget_->SetAccessibleState( | |
901 widget_delegate_->GetAccessibleWindowState()); | |
902 | |
903 if (widget_delegate_->IsModal()) | |
904 native_widget_->BecomeModal(); | |
905 } | |
906 | |
907 void Widget::OnNativeWidgetDestroying() { | |
908 FOR_EACH_OBSERVER(Observer, observers_, OnWidgetClosing(this)); | |
909 if (non_client_view_) | |
910 non_client_view_->WindowClosing(); | |
911 widget_delegate_->WindowClosing(); | |
912 } | |
913 | |
914 void Widget::OnNativeWidgetDestroyed() { | |
915 widget_delegate_->DeleteDelegate(); | |
916 widget_delegate_ = NULL; | |
917 } | |
918 | |
919 gfx::Size Widget::GetMinimumSize() { | |
920 return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size(); | |
921 } | |
922 | |
923 void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) { | |
924 root_view_->SetSize(new_size); | |
925 | |
926 // Size changed notifications can fire prior to full initialization | |
927 // i.e. during session restore. Avoid saving session state during these | |
928 // startup procedures. | |
929 if (native_widget_initialized_) | |
930 SaveWindowPlacement(); | |
931 } | |
932 | |
933 void Widget::OnNativeWidgetBeginUserBoundsChange() { | |
934 widget_delegate_->OnWindowBeginUserBoundsChange(); | |
935 } | |
936 | |
937 void Widget::OnNativeWidgetEndUserBoundsChange() { | |
938 widget_delegate_->OnWindowEndUserBoundsChange(); | |
939 } | |
940 | |
941 bool Widget::HasFocusManager() const { | |
942 return !!focus_manager_.get(); | |
943 } | |
944 | |
945 bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) { | |
946 ui::Compositor* compositor = GetCompositor(); | |
947 if (!compositor) | |
948 return false; | |
949 | |
950 // If the root view is animating, it is likely that it does not cover the same | |
951 // set of pixels it did at the last frame, so we must clear when compositing | |
952 // to avoid leaving ghosts. | |
953 bool force_clear = false; | |
954 if (GetRootView()->layer()) { | |
955 const ui::Transform& layer_transform = GetRootView()->layer()->transform(); | |
956 if (layer_transform != GetRootView()->GetTransform()) { | |
957 // The layer has not caught up to the view (i.e., the layer is still | |
958 // animating), and so a clear is required. | |
959 force_clear = true; | |
960 } else { | |
961 // Determine if the layer fills the client area. | |
962 gfx::Rect layer_bounds = GetRootView()->layer()->bounds(); | |
963 layer_transform.TransformRect(&layer_bounds); | |
964 gfx::Rect client_bounds = GetClientAreaScreenBounds(); | |
965 // Translate bounds to origin (client area bounds are offset to account | |
966 // for buttons, etc). | |
967 client_bounds.set_origin(gfx::Point(0, 0)); | |
968 if (!layer_bounds.Contains(client_bounds)) { | |
969 // It doesn't, and so a clear is required. | |
970 force_clear = true; | |
971 } | |
972 } | |
973 } | |
974 | |
975 compositor->Draw(force_clear); | |
976 return true; | |
977 } | |
978 | |
979 void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) { | |
980 GetRootView()->Paint(canvas); | |
981 } | |
982 | |
983 int Widget::GetNonClientComponent(const gfx::Point& point) { | |
984 return non_client_view_ ? | |
985 non_client_view_->NonClientHitTest(point) : | |
986 HTNOWHERE; | |
987 } | |
988 | |
989 bool Widget::OnKeyEvent(const KeyEvent& event) { | |
990 ScopedEvent scoped(this, event); | |
991 return static_cast<internal::RootView*>(GetRootView())->OnKeyEvent(event); | |
992 } | |
993 | |
994 bool Widget::OnMouseEvent(const MouseEvent& event) { | |
995 ScopedEvent scoped(this, event); | |
996 switch (event.type()) { | |
997 case ui::ET_MOUSE_PRESSED: | |
998 last_mouse_event_was_move_ = false; | |
999 // Make sure we're still visible before we attempt capture as the mouse | |
1000 // press processing may have made the window hide (as happens with menus). | |
1001 if (GetRootView()->OnMousePressed(event) && IsVisible()) { | |
1002 is_mouse_button_pressed_ = true; | |
1003 if (!native_widget_->HasMouseCapture()) | |
1004 native_widget_->SetMouseCapture(); | |
1005 return true; | |
1006 } | |
1007 return false; | |
1008 case ui::ET_MOUSE_RELEASED: | |
1009 last_mouse_event_was_move_ = false; | |
1010 is_mouse_button_pressed_ = false; | |
1011 // Release capture first, to avoid confusion if OnMouseReleased blocks. | |
1012 if (native_widget_->HasMouseCapture() && | |
1013 ShouldReleaseCaptureOnMouseReleased()) { | |
1014 native_widget_->ReleaseMouseCapture(); | |
1015 } | |
1016 GetRootView()->OnMouseReleased(event); | |
1017 return (event.flags() & ui::EF_IS_NON_CLIENT) ? false : true; | |
1018 case ui::ET_MOUSE_MOVED: | |
1019 case ui::ET_MOUSE_DRAGGED: | |
1020 if (native_widget_->HasMouseCapture() && is_mouse_button_pressed_) { | |
1021 last_mouse_event_was_move_ = false; | |
1022 GetRootView()->OnMouseDragged(event); | |
1023 } else if (!last_mouse_event_was_move_ || | |
1024 last_mouse_event_position_ != event.location()) { | |
1025 last_mouse_event_position_ = event.location(); | |
1026 last_mouse_event_was_move_ = true; | |
1027 GetRootView()->OnMouseMoved(event); | |
1028 } | |
1029 return false; | |
1030 case ui::ET_MOUSE_EXITED: | |
1031 last_mouse_event_was_move_ = false; | |
1032 GetRootView()->OnMouseExited(event); | |
1033 return false; | |
1034 case ui::ET_MOUSEWHEEL: | |
1035 return GetRootView()->OnMouseWheel( | |
1036 reinterpret_cast<const MouseWheelEvent&>(event)); | |
1037 default: | |
1038 return false; | |
1039 } | |
1040 return true; | |
1041 } | |
1042 | |
1043 void Widget::OnMouseCaptureLost() { | |
1044 if (is_mouse_button_pressed_) | |
1045 GetRootView()->OnMouseCaptureLost(); | |
1046 is_mouse_button_pressed_ = false; | |
1047 } | |
1048 | |
1049 ui::TouchStatus Widget::OnTouchEvent(const TouchEvent& event) { | |
1050 ScopedEvent scoped(this, event); | |
1051 return static_cast<internal::RootView*>(GetRootView())->OnTouchEvent(event); | |
1052 } | |
1053 | |
1054 bool Widget::ExecuteCommand(int command_id) { | |
1055 return widget_delegate_->ExecuteWindowsCommand(command_id); | |
1056 } | |
1057 | |
1058 InputMethod* Widget::GetInputMethodDirect() { | |
1059 return input_method_.get(); | |
1060 } | |
1061 | |
1062 Widget* Widget::AsWidget() { | |
1063 return this; | |
1064 } | |
1065 | |
1066 const Widget* Widget::AsWidget() const { | |
1067 return this; | |
1068 } | |
1069 | |
1070 //////////////////////////////////////////////////////////////////////////////// | |
1071 // Widget, FocusTraversable implementation: | |
1072 | |
1073 FocusSearch* Widget::GetFocusSearch() { | |
1074 return root_view_->GetFocusSearch(); | |
1075 } | |
1076 | |
1077 FocusTraversable* Widget::GetFocusTraversableParent() { | |
1078 // We are a proxy to the root view, so we should be bypassed when traversing | |
1079 // up and as a result this should not be called. | |
1080 NOTREACHED(); | |
1081 return NULL; | |
1082 } | |
1083 | |
1084 View* Widget::GetFocusTraversableParentView() { | |
1085 // We are a proxy to the root view, so we should be bypassed when traversing | |
1086 // up and as a result this should not be called. | |
1087 NOTREACHED(); | |
1088 return NULL; | |
1089 } | |
1090 | |
1091 //////////////////////////////////////////////////////////////////////////////// | |
1092 // Widget, protected: | |
1093 | |
1094 internal::RootView* Widget::CreateRootView() { | |
1095 return new internal::RootView(this); | |
1096 } | |
1097 | |
1098 void Widget::DestroyRootView() { | |
1099 non_client_view_ = NULL; | |
1100 root_view_.reset(); | |
1101 // Input method has to be destroyed before focus manager. | |
1102 input_method_.reset(); | |
1103 // Defer focus manager's destruction. This is for the case when the | |
1104 // focus manager is referenced by a child NativeWidgetGtk (e.g. TabbedPane in | |
1105 // a dialog). When gtk_widget_destroy is called on the parent, the destroy | |
1106 // signal reaches parent first and then the child. Thus causing the parent | |
1107 // NativeWidgetGtk's dtor executed before the child's. If child's view | |
1108 // hierarchy references this focus manager, it crashes. This will defer focus | |
1109 // manager's destruction after child NativeWidgetGtk's dtor. | |
1110 FocusManager* focus_manager = focus_manager_.release(); | |
1111 if (focus_manager) | |
1112 MessageLoop::current()->DeleteSoon(FROM_HERE, focus_manager); | |
1113 } | |
1114 | |
1115 //////////////////////////////////////////////////////////////////////////////// | |
1116 // Widget, private: | |
1117 | |
1118 bool Widget::ShouldReleaseCaptureOnMouseReleased() const { | |
1119 return true; | |
1120 } | |
1121 | |
1122 void Widget::SetInactiveRenderingDisabled(bool value) { | |
1123 disable_inactive_rendering_ = value; | |
1124 // We need to always notify the NonClientView so that it can trigger a paint. | |
1125 // TODO: what's really needed is a way to know when either the active state | |
1126 // changes or |disable_inactive_rendering_| changes. | |
1127 if (non_client_view_) | |
1128 non_client_view_->SetInactiveRenderingDisabled(value); | |
1129 native_widget_->SetInactiveRenderingDisabled(value); | |
1130 } | |
1131 | |
1132 void Widget::SaveWindowPlacement() { | |
1133 // The window delegate does the actual saving for us. It seems like (judging | |
1134 // by go/crash) that in some circumstances we can end up here after | |
1135 // WM_DESTROY, at which point the window delegate is likely gone. So just | |
1136 // bail. | |
1137 if (!widget_delegate_) | |
1138 return; | |
1139 | |
1140 ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL; | |
1141 gfx::Rect bounds; | |
1142 native_widget_->GetWindowPlacement(&bounds, &show_state); | |
1143 widget_delegate_->SaveWindowPlacement(bounds, show_state); | |
1144 } | |
1145 | |
1146 void Widget::SetInitialBounds(const gfx::Rect& bounds) { | |
1147 if (!non_client_view_) | |
1148 return; | |
1149 | |
1150 gfx::Rect saved_bounds; | |
1151 if (GetSavedWindowPlacement(&saved_bounds, &saved_show_state_)) { | |
1152 if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED) { | |
1153 // If we're going to maximize, wait until Show is invoked to set the | |
1154 // bounds. That way we avoid a noticable resize. | |
1155 initial_restored_bounds_ = saved_bounds; | |
1156 } else { | |
1157 SetBounds(saved_bounds); | |
1158 } | |
1159 } else { | |
1160 if (bounds.IsEmpty()) { | |
1161 // No initial bounds supplied, so size the window to its content and | |
1162 // center over its parent. | |
1163 native_widget_->CenterWindow(non_client_view_->GetPreferredSize()); | |
1164 } else { | |
1165 // Use the supplied initial bounds. | |
1166 SetBoundsConstrained(bounds); | |
1167 } | |
1168 } | |
1169 } | |
1170 | |
1171 bool Widget::GetSavedWindowPlacement(gfx::Rect* bounds, | |
1172 ui::WindowShowState* show_state) { | |
1173 // First we obtain the window's saved show-style and store it. We need to do | |
1174 // this here, rather than in Show() because by the time Show() is called, | |
1175 // the window's size will have been reset (below) and the saved maximized | |
1176 // state will have been lost. Sadly there's no way to tell on Windows when | |
1177 // a window is restored from maximized state, so we can't more accurately | |
1178 // track maximized state independently of sizing information. | |
1179 | |
1180 // Restore the window's placement from the controller. | |
1181 if (widget_delegate_->GetSavedWindowPlacement(bounds, show_state)) { | |
1182 if (!widget_delegate_->ShouldRestoreWindowSize()) { | |
1183 bounds->set_size(non_client_view_->GetPreferredSize()); | |
1184 } else { | |
1185 gfx::Size minimum_size = GetMinimumSize(); | |
1186 // Make sure the bounds are at least the minimum size. | |
1187 if (bounds->width() < minimum_size.width()) | |
1188 bounds->set_width(minimum_size.width()); | |
1189 | |
1190 if (bounds->height() < minimum_size.height()) | |
1191 bounds->set_height(minimum_size.height()); | |
1192 } | |
1193 return true; | |
1194 } | |
1195 return false; | |
1196 } | |
1197 | |
1198 void Widget::ReplaceInputMethod(InputMethod* input_method) { | |
1199 input_method_.reset(input_method); | |
1200 // TODO(oshima): Gtk's textfield doesn't need views InputMethod. | |
1201 // Remove this check once gtk is removed. | |
1202 if (input_method) { | |
1203 input_method->set_delegate(native_widget_); | |
1204 input_method->Init(this); | |
1205 } | |
1206 } | |
1207 | |
1208 namespace internal { | |
1209 | |
1210 //////////////////////////////////////////////////////////////////////////////// | |
1211 // internal::NativeWidgetPrivate, NativeWidget implementation: | |
1212 | |
1213 internal::NativeWidgetPrivate* NativeWidgetPrivate::AsNativeWidgetPrivate() { | |
1214 return this; | |
1215 } | |
1216 | |
1217 } // namespace internal | |
1218 } // namespace views | |
OLD | NEW |