Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(944)

Side by Side Diff: chrome/browser/chromeos/frame/panel_controller.cc

Issue 9664072: Removing WmIpc and related files from ChromeOS (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Copyright Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/chromeos/frame/panel_controller.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/singleton.h"
12 #include "base/string_util.h"
13 #include "base/time.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/common/chrome_notification_types.h"
16 #include "content/public/browser/notification_service.h"
17 #include "grit/generated_resources.h"
18 #include "grit/theme_resources.h"
19 #include "grit/theme_resources_standard.h"
20 #include "grit/ui_resources.h"
21 #include "third_party/cros_system_api/window_manager/chromeos_wm_ipc_enums.h"
22 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
23 #include "third_party/skia/include/effects/SkGradientShader.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/gfx/canvas.h"
26 #include "ui/views/controls/button/image_button.h"
27 #include "ui/views/controls/image_view.h"
28 #include "ui/views/controls/label.h"
29 #include "ui/views/events/event.h"
30 #include "ui/views/painter.h"
31 #include "ui/views/view.h"
32 #include "ui/views/widget/widget.h"
33
34 #if defined(TOOLKIT_USES_GTK)
35 #include "chrome/browser/chromeos/legacy_window_manager/wm_ipc.h"
36 #endif
37
38 namespace chromeos {
39
40 static int close_button_width;
41 static int close_button_height;
42 static SkBitmap* close_button_n;
43 static SkBitmap* close_button_m;
44 static SkBitmap* close_button_h;
45 static SkBitmap* close_button_p;
46 static gfx::Font* active_font = NULL;
47 static gfx::Font* inactive_font = NULL;
48
49 namespace {
50
51 const int kTitleHeight = 24;
52 const int kTitleIconSize = 16;
53 const int kTitleWidthPad = 4;
54 const int kTitleHeightPad = 4;
55 const int kTitleCornerRadius = 4;
56 const int kTitleCloseButtonPad = 6;
57 const SkColor kTitleActiveGradientStart = SK_ColorWHITE;
58 const SkColor kTitleActiveGradientEnd = 0xffe7edf1;
59 const SkColor kTitleUrgentGradientStart = 0xfffea044;
60 const SkColor kTitleUrgentGradientEnd = 0xfffa983a;
61 const SkColor kTitleActiveTextColor = SK_ColorBLACK;
62 const SkColor kTitleInactiveTextColor = SK_ColorBLACK;
63 const SkColor kTitleUrgentTextColor = SK_ColorWHITE;
64 const SkColor kTitleCloseButtonColor = SK_ColorBLACK;
65 // Delay before the urgency can be set after it has been cleared.
66 const base::TimeDelta kSetUrgentDelay = base::TimeDelta::FromMilliseconds(500);
67
68 // Used to draw the background of the panel title window.
69 class TitleBackgroundPainter : public views::Painter {
70 public:
71 explicit TitleBackgroundPainter(PanelController* controller)
72 : panel_controller_(controller) { }
73
74 private:
75 // Overridden from views::Painter:
76 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE {
77 SkPath path;
78 SkRect rect;
79 rect.iset(0, 0, size.width(), size.height());
80 SkScalar corners[] = {
81 kTitleCornerRadius, kTitleCornerRadius,
82 kTitleCornerRadius, kTitleCornerRadius,
83 0, 0,
84 0, 0
85 };
86 path.addRoundRect(rect, corners);
87 SkPoint points[2];
88 points[0].iset(0, 0);
89 points[1].iset(0, size.height());
90 SkColor colors[2] = { kTitleActiveGradientStart, kTitleActiveGradientEnd };
91 if (panel_controller_->urgent()) {
92 colors[0] = kTitleUrgentGradientStart;
93 colors[1] = kTitleUrgentGradientEnd;
94 }
95 SkShader* s = SkGradientShader::CreateLinear(
96 points, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
97 SkPaint paint;
98 paint.setStyle(SkPaint::kFill_Style);
99 paint.setAntiAlias(true);
100 paint.setShader(s);
101 // Need to unref shader, otherwise never deleted.
102 s->unref();
103 canvas->sk_canvas()->drawPath(path, paint);
104 }
105
106 PanelController* panel_controller_;
107 };
108
109 static bool resources_initialized;
110 static void InitializeResources() {
111 if (resources_initialized) {
112 return;
113 }
114
115 resources_initialized = true;
116 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
117 gfx::Font base_font = rb.GetFont(ResourceBundle::BaseFont);
118 // Title fonts are the same for active and inactive.
119 inactive_font = new gfx::Font(base_font.DeriveFont(0, gfx::Font::BOLD));
120 active_font = inactive_font;
121 close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
122 close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
123 close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
124 close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
125 close_button_width = close_button_n->width();
126 close_button_height = close_button_n->height();
127 }
128
129 } // namespace
130
131 PanelController::PanelController(Delegate* delegate,
132 GtkWindow* window)
133 : delegate_(delegate),
134 panel_(window),
135 panel_xid_(ui::GetX11WindowFromGtkWidget(GTK_WIDGET(panel_))),
136 title_window_(NULL),
137 title_(NULL),
138 title_content_(NULL),
139 expanded_(true),
140 mouse_down_(false),
141 dragging_(false),
142 client_event_handler_id_(0),
143 focused_(false),
144 urgent_(false) {
145 }
146
147 void PanelController::Init(bool initial_focus,
148 const gfx::Rect& window_bounds,
149 XID creator_xid,
150 WmIpcPanelUserResizeType resize_type) {
151 gfx::Rect title_bounds(0, 0, window_bounds.width(), kTitleHeight);
152
153 title_window_ = new views::Widget;
154 views::Widget::InitParams params(
155 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
156 params.transparent = true;
157 params.bounds = title_bounds;
158 title_window_->Init(params);
159
160 #if defined(TOOLKIT_USES_GTK)
161 gtk_widget_set_size_request(title_window_->GetNativeView(),
162 title_bounds.width(), title_bounds.height());
163 title_ = title_window_->GetNativeView();
164 title_xid_ = ui::GetX11WindowFromGtkWidget(title_);
165
166 WmIpc::instance()->SetWindowType(
167 title_,
168 WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR,
169 NULL);
170 std::vector<int> type_params;
171 type_params.push_back(title_xid_);
172 type_params.push_back(expanded_ ? 1 : 0);
173 type_params.push_back(initial_focus ? 1 : 0);
174 type_params.push_back(creator_xid);
175 type_params.push_back(resize_type);
176 WmIpc::instance()->SetWindowType(
177 GTK_WIDGET(panel_),
178 WM_IPC_WINDOW_CHROME_PANEL_CONTENT,
179 &type_params);
180
181 client_event_handler_id_ = g_signal_connect(
182 panel_, "client-event", G_CALLBACK(OnPanelClientEvent), this);
183 #endif
184
185 title_content_ = new TitleContentView(this);
186 title_window_->SetContentsView(title_content_);
187 UpdateTitleBar();
188 title_window_->Show();
189 }
190
191 void PanelController::UpdateTitleBar() {
192 if (!delegate_ || !title_window_)
193 return;
194 title_content_->title_label()->SetText(delegate_->GetPanelTitle());
195 title_content_->title_icon()->SetImage(delegate_->GetPanelIcon());
196 }
197
198 void PanelController::SetUrgent(bool urgent) {
199 if (!urgent)
200 urgent_cleared_time_ = base::TimeTicks::Now();
201 if (urgent == urgent_)
202 return;
203 if (urgent && focused_)
204 return; // Don't set urgency for focused panels.
205 if (urgent && base::TimeTicks::Now() < urgent_cleared_time_ + kSetUrgentDelay)
206 return; // Don't set urgency immediately after clearing it.
207 urgent_ = urgent;
208 if (title_window_) {
209 gtk_window_set_urgency_hint(panel_, urgent ? TRUE : FALSE);
210 title_content_->title_label()->SetDisabledColor(urgent ?
211 kTitleUrgentTextColor : kTitleInactiveTextColor);
212 title_content_->SchedulePaint();
213 }
214 }
215
216 bool PanelController::TitleMousePressed(const views::MouseEvent& event) {
217 if (!event.IsOnlyLeftMouseButton())
218 return false;
219 if (event.type() != ui::ET_MOUSE_PRESSED) {
220 NOTREACHED();
221 return false;
222 }
223 DCHECK(title_);
224 // Get the last titlebar width that we saw in a ConfigureNotify event -- we
225 // need to give drag positions in terms of the top-right corner of the
226 // titlebar window. See WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED's declaration
227 // for details.
228 gint title_width = 1;
229 gtk_window_get_size(GTK_WINDOW(title_), &title_width, NULL);
230
231 mouse_down_ = true;
232 mouse_down_offset_x_ = event.x() - title_width;
233 mouse_down_offset_y_ = event.y();
234 dragging_ = false;
235
236 #if defined(TOOLKIT_USES_GTK)
237 const GdkEvent* gdk_event = event.gdk_event();
238 GdkEventButton last_button_event = gdk_event->button;
239 mouse_down_abs_x_ = last_button_event.x_root;
240 mouse_down_abs_y_ = last_button_event.y_root;
241 #else
242 const XEvent* xev = event.native_event();
243 gfx::Point abs_location = RootLocationFromXEvent(xev);
244 mouse_down_abs_x_ = abs_location.x();
245 mouse_down_abs_y_ = abs_location.y();
246 #endif
247 return true;
248 }
249
250 void PanelController::TitleMouseReleased(const views::MouseEvent& event) {
251 if (event.IsLeftMouseButton())
252 TitleMouseCaptureLost();
253 }
254
255 void PanelController::TitleMouseCaptureLost() {
256 // Only handle clicks that started in our window.
257 if (!mouse_down_)
258 return;
259
260 mouse_down_ = false;
261 if (!dragging_) {
262 if (expanded_) {
263 // Always activate the panel here, even if we are about to minimize it.
264 // This lets panels like GTalk know that they have been acknowledged, so
265 // they don't change the title again (which would trigger SetUrgent).
266 // Activating the panel also clears the urgent state.
267 delegate_->ActivatePanel();
268 SetState(PanelController::MINIMIZED);
269 } else {
270 // If we're expanding the panel, do so before focusing it. This lets the
271 // window manager know that the panel is being expanded in response to a
272 // user action; see http://crosbug.com/14735.
273 SetState(PanelController::EXPANDED);
274 delegate_->ActivatePanel();
275 }
276 } else {
277 #if defined(TOOLKIT_USES_GTK)
278 WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAG_COMPLETE);
279 msg.set_param(0, panel_xid_);
280 WmIpc::instance()->SendMessage(msg);
281 #endif
282 dragging_ = false;
283 }
284 }
285
286 void PanelController::SetState(State state) {
287 #if defined(TOOLKIT_USES_GTK)
288 WmIpc::Message msg(WM_IPC_MESSAGE_WM_SET_PANEL_STATE);
289 msg.set_param(0, panel_xid_);
290 msg.set_param(1, state == EXPANDED);
291 WmIpc::instance()->SendMessage(msg);
292 #endif
293 }
294
295 bool PanelController::TitleMouseDragged(const views::MouseEvent& event) {
296 if (!mouse_down_)
297 return false;
298 if (event.type() != ui::ET_MOUSE_MOVED &&
299 event.type() != ui::ET_MOUSE_DRAGGED) {
300 NOTREACHED();
301 return false;
302 }
303
304 const GdkEvent* gdk_event = event.gdk_event();
305 GdkEventMotion last_motion_event = gdk_event->motion;
306 int x_root = last_motion_event.x_root;
307 int y_root = last_motion_event.y_root;
308
309 if (!dragging_) {
310 if (views::View::ExceededDragThreshold(x_root - mouse_down_abs_x_,
311 y_root - mouse_down_abs_y_)) {
312 dragging_ = true;
313 }
314 }
315 #if defined(TOOLKIT_USES_GTK)
316 if (dragging_) {
317 WmIpc::Message msg(WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED);
318 msg.set_param(0, panel_xid_);
319 msg.set_param(1, x_root - mouse_down_offset_x_);
320 msg.set_param(2, y_root - mouse_down_offset_y_);
321 WmIpc::instance()->SendMessage(msg);
322 }
323 #endif
324 return true;
325 }
326
327 // static
328 bool PanelController::OnPanelClientEvent(
329 GtkWidget* widget,
330 GdkEventClient* event,
331 PanelController* panel_controller) {
332 return panel_controller->PanelClientEvent(event);
333 }
334
335 void PanelController::OnFocusIn() {
336 if (title_window_)
337 title_content_->OnFocusIn();
338 focused_ = true;
339 // Clear urgent when focused.
340 SetUrgent(false);
341 }
342
343 void PanelController::OnFocusOut() {
344 focused_ = false;
345 if (title_window_)
346 title_content_->OnFocusOut();
347 }
348
349 bool PanelController::PanelClientEvent(GdkEventClient* event) {
350 #if defined(TOOLKIT_USES_GTK)
351 WmIpc::Message msg;
352 WmIpc::instance()->DecodeMessage(*event, &msg);
353 if (msg.type() == WM_IPC_MESSAGE_CHROME_NOTIFY_PANEL_STATE) {
354 bool new_state = msg.param(0);
355 if (expanded_ != new_state) {
356 expanded_ = new_state;
357 State state = new_state ? EXPANDED : MINIMIZED;
358 content::NotificationService::current()->Notify(
359 chrome::NOTIFICATION_PANEL_STATE_CHANGED,
360 content::Source<PanelController>(this),
361 content::Details<State>(&state));
362 }
363 }
364 #endif
365 return true;
366 }
367
368 void PanelController::Close() {
369 if (client_event_handler_id_ > 0) {
370 g_signal_handler_disconnect(panel_, client_event_handler_id_);
371 client_event_handler_id_ = 0;
372 }
373 // ignore if the title window is already closed.
374 if (title_window_) {
375 title_window_->Close();
376 title_window_ = NULL;
377 title_ = NULL;
378 title_content_->OnClose();
379 title_content_ = NULL;
380 }
381 }
382
383 void PanelController::OnCloseButtonPressed() {
384 DCHECK(title_content_);
385 if (title_window_) {
386 if (delegate_) {
387 if (!delegate_->CanClosePanel())
388 return;
389 delegate_->ClosePanel();
390 }
391 Close();
392 }
393 }
394
395 PanelController::TitleContentView::TitleContentView(
396 PanelController* panel_controller)
397 : panel_controller_(panel_controller) {
398 VLOG(1) << "panel: c " << this;
399 InitializeResources();
400 close_button_ = new views::ImageButton(this);
401 close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
402 close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
403 close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
404 close_button_->SetBackground(
405 kTitleCloseButtonColor, close_button_n, close_button_m);
406 AddChildView(close_button_);
407
408 title_icon_ = new views::ImageView();
409 AddChildView(title_icon_);
410 title_label_ = new views::Label(string16());
411 title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
412 title_label_->SetAutoColorReadabilityEnabled(false);
413 title_label_->SetEnabledColor(kTitleActiveTextColor);
414 title_label_->SetDisabledColor(kTitleInactiveTextColor);
415 title_label_->SetEnabled(false);
416 AddChildView(title_label_);
417
418 set_background(
419 views::Background::CreateBackgroundPainter(
420 true, new TitleBackgroundPainter(panel_controller)));
421 OnFocusOut();
422 }
423
424 void PanelController::TitleContentView::Layout() {
425 int close_button_x = bounds().width() -
426 (close_button_width + kTitleCloseButtonPad);
427 close_button_->SetBounds(
428 close_button_x,
429 (bounds().height() - close_button_height) / 2,
430 close_button_width,
431 close_button_height);
432 title_icon_->SetBounds(
433 kTitleWidthPad,
434 kTitleHeightPad,
435 kTitleIconSize,
436 kTitleIconSize);
437 int title_x = kTitleWidthPad * 2 + kTitleIconSize;
438 title_label_->SetBounds(
439 title_x,
440 0,
441 close_button_x - (title_x + kTitleCloseButtonPad),
442 bounds().height());
443 }
444
445 bool PanelController::TitleContentView::OnMousePressed(
446 const views::MouseEvent& event) {
447 return panel_controller_->TitleMousePressed(event);
448 }
449
450 void PanelController::TitleContentView::OnMouseReleased(
451 const views::MouseEvent& event) {
452 panel_controller_->TitleMouseReleased(event);
453 }
454
455 void PanelController::TitleContentView::OnMouseCaptureLost() {
456 panel_controller_->TitleMouseCaptureLost();
457 }
458
459 bool PanelController::TitleContentView::OnMouseDragged(
460 const views::MouseEvent& event) {
461 return panel_controller_->TitleMouseDragged(event);
462 }
463
464 void PanelController::TitleContentView::OnFocusIn() {
465 title_label_->SetEnabled(true);
466 title_label_->SetFont(*active_font);
467 Layout();
468 SchedulePaint();
469 }
470
471 void PanelController::TitleContentView::OnFocusOut() {
472 title_label_->SetEnabled(false);
473 title_label_->SetFont(*inactive_font);
474 Layout();
475 SchedulePaint();
476 }
477
478 void PanelController::TitleContentView::OnClose() {
479 panel_controller_ = NULL;
480 }
481
482 void PanelController::TitleContentView::ButtonPressed(
483 views::Button* sender, const views::Event& event) {
484 if (panel_controller_ && sender == close_button_)
485 panel_controller_->OnCloseButtonPressed();
486 }
487
488 PanelController::TitleContentView::~TitleContentView() {
489 VLOG(1) << "panel: delete " << this;
490 }
491
492 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/frame/panel_controller.h ('k') | chrome/browser/chromeos/legacy_window_manager/wm_ipc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698