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

Side by Side Diff: remoting/host/disconnect_window_linux.cc

Issue 10386181: Fix remoting_unittests compilation with aura (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « remoting/host/disconnect_window_gtk.cc ('k') | remoting/remoting.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "remoting/host/disconnect_window.h"
6
7 #include <gtk/gtk.h>
8 #include <math.h>
9
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h"
14 #include "remoting/host/chromoting_host.h"
15 #include "remoting/host/ui_strings.h"
16 #include "ui/base/gtk/gtk_signal.h"
17
18 namespace remoting {
19
20 class DisconnectWindowLinux : public DisconnectWindow {
21 public:
22 DisconnectWindowLinux();
23 virtual ~DisconnectWindowLinux();
24
25 virtual void Show(ChromotingHost* host,
26 const DisconnectCallback& disconnect_callback,
27 const std::string& username) OVERRIDE;
28 virtual void Hide() OVERRIDE;
29
30 private:
31 CHROMEGTK_CALLBACK_1(DisconnectWindowLinux, gboolean, OnDelete, GdkEvent*);
32 CHROMEGTK_CALLBACK_0(DisconnectWindowLinux, void, OnClicked);
33 CHROMEGTK_CALLBACK_1(DisconnectWindowLinux, gboolean, OnConfigure,
34 GdkEventConfigure*);
35 CHROMEGTK_CALLBACK_1(DisconnectWindowLinux, gboolean, OnButtonPress,
36 GdkEventButton*);
37
38 void CreateWindow(const UiStrings& ui_strings);
39
40 DisconnectCallback disconnect_callback_;
41 GtkWidget* disconnect_window_;
42 GtkWidget* message_;
43 GtkWidget* button_;
44
45 // Used to distinguish resize events from other types of "configure-event"
46 // notifications.
47 int current_width_;
48 int current_height_;
49
50 DISALLOW_COPY_AND_ASSIGN(DisconnectWindowLinux);
51 };
52
53 DisconnectWindowLinux::DisconnectWindowLinux()
54 : disconnect_window_(NULL),
55 current_width_(0),
56 current_height_(0) {
57 }
58
59 DisconnectWindowLinux::~DisconnectWindowLinux() {
60 }
61
62 void DisconnectWindowLinux::CreateWindow(const UiStrings& ui_strings) {
63 if (disconnect_window_) return;
64
65 disconnect_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
66 GtkWindow* window = GTK_WINDOW(disconnect_window_);
67
68 g_signal_connect(disconnect_window_, "delete-event",
69 G_CALLBACK(OnDeleteThunk), this);
70 gtk_window_set_title(window, UTF16ToUTF8(ui_strings.product_name).c_str());
71 gtk_window_set_resizable(window, FALSE);
72
73 // Try to keep the window always visible.
74 gtk_window_stick(window);
75 gtk_window_set_keep_above(window, TRUE);
76
77 // Remove window titlebar.
78 gtk_window_set_decorated(window, FALSE);
79
80 // In case the titlebar is still there, try to remove some of the buttons.
81 // Utility windows have no minimize button or taskbar presence.
82 gtk_window_set_type_hint(window, GDK_WINDOW_TYPE_HINT_UTILITY);
83 gtk_window_set_deletable(window, FALSE);
84
85 // Allow custom rendering of the background pixmap.
86 gtk_widget_set_app_paintable(disconnect_window_, TRUE);
87
88 // Handle window resizing, to regenerate the background pixmap and window
89 // shape bitmap. The stored width & height need to be initialized here
90 // in case the window is created a second time (the size of the previous
91 // window would be remembered, preventing the generation of bitmaps for the
92 // new window).
93 current_height_ = current_width_ = 0;
94 g_signal_connect(disconnect_window_, "configure-event",
95 G_CALLBACK(OnConfigureThunk), this);
96
97 // Handle mouse events to allow the user to drag the window around.
98 gtk_widget_set_events(disconnect_window_, GDK_BUTTON_PRESS_MASK);
99 g_signal_connect(disconnect_window_, "button-press-event",
100 G_CALLBACK(OnButtonPressThunk), this);
101
102 // All magic numbers taken from screen shots provided by UX.
103 // The alignment sets narrow margins at the top and bottom, compared with
104 // left and right. The left margin is made larger to accommodate the
105 // window movement gripper.
106 GtkWidget* align = gtk_alignment_new(0, 0, 1, 1);
107 gtk_alignment_set_padding(GTK_ALIGNMENT(align), 8, 8, 24, 12);
108 gtk_container_add(GTK_CONTAINER(window), align);
109
110 GtkWidget* button_row = gtk_hbox_new(FALSE, 12);
111 gtk_container_add(GTK_CONTAINER(align), button_row);
112
113 button_ = gtk_button_new_with_label(
114 UTF16ToUTF8(ui_strings.disconnect_button_text_plus_shortcut).c_str());
115 gtk_box_pack_end(GTK_BOX(button_row), button_, FALSE, FALSE, 0);
116
117 g_signal_connect(button_, "clicked", G_CALLBACK(OnClickedThunk), this);
118
119 message_ = gtk_label_new(NULL);
120 gtk_box_pack_end(GTK_BOX(button_row), message_, FALSE, FALSE, 0);
121
122 // Override any theme setting for the text color, so that the text is
123 // readable against the window's background pixmap.
124 PangoAttrList* attributes = pango_attr_list_new();
125 PangoAttribute* text_color = pango_attr_foreground_new(0, 0, 0);
126 pango_attr_list_insert(attributes, text_color);
127 gtk_label_set_attributes(GTK_LABEL(message_), attributes);
128
129 gtk_widget_show_all(disconnect_window_);
130 }
131
132 void DisconnectWindowLinux::Show(ChromotingHost* host,
133 const DisconnectCallback& disconnect_callback,
134 const std::string& username) {
135 disconnect_callback_ = disconnect_callback;
136 CreateWindow(host->ui_strings());
137
138 string16 text = ReplaceStringPlaceholders(
139 host->ui_strings().disconnect_message, UTF8ToUTF16(username), NULL);
140 gtk_label_set_text(GTK_LABEL(message_), UTF16ToUTF8(text).c_str());
141 gtk_window_present(GTK_WINDOW(disconnect_window_));
142 }
143
144 void DisconnectWindowLinux::Hide() {
145 if (disconnect_window_) {
146 gtk_widget_destroy(disconnect_window_);
147 disconnect_window_ = NULL;
148 }
149 }
150
151 void DisconnectWindowLinux::OnClicked(GtkWidget* button) {
152 CHECK(!disconnect_callback_.is_null());
153
154 disconnect_callback_.Run();
155 Hide();
156 }
157
158 gboolean DisconnectWindowLinux::OnDelete(GtkWidget* window, GdkEvent* event) {
159 CHECK(!disconnect_callback_.is_null());
160
161 disconnect_callback_.Run();
162 Hide();
163
164 return TRUE;
165 }
166
167 namespace {
168 // Helper function for creating a rectangular path with rounded corners, as
169 // Cairo doesn't have this facility. |radius| is the arc-radius of each
170 // corner. The bounding rectangle extends from (0, 0) to (width, height).
171 void AddRoundRectPath(cairo_t* cairo_context, int width, int height,
172 int radius) {
173 cairo_new_sub_path(cairo_context);
174 cairo_arc(cairo_context, width - radius, radius, radius, -M_PI_2, 0);
175 cairo_arc(cairo_context, width - radius, height - radius, radius, 0, M_PI_2);
176 cairo_arc(cairo_context, radius, height - radius, radius, M_PI_2, 2 * M_PI_2);
177 cairo_arc(cairo_context, radius, radius, radius, 2 * M_PI_2, 3 * M_PI_2);
178 cairo_close_path(cairo_context);
179 }
180
181 } // namespace
182
183 gboolean DisconnectWindowLinux::OnConfigure(GtkWidget* widget,
184 GdkEventConfigure* event) {
185 // Only generate bitmaps if the size has actually changed.
186 if (event->width == current_width_ && event->height == current_height_)
187 return FALSE;
188
189 current_width_ = event->width;
190 current_height_ = event->height;
191
192 // Create the depth 1 pixmap for the window shape.
193 GdkPixmap* shape_mask = gdk_pixmap_new(NULL, current_width_, current_height_,
194 1);
195 cairo_t* cairo_context = gdk_cairo_create(shape_mask);
196
197 // Set the arc radius for the corners.
198 const int kCornerRadius = 6;
199
200 // Initialize the whole bitmap to be transparent.
201 cairo_set_source_rgba(cairo_context, 0, 0, 0, 0);
202 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
203 cairo_paint(cairo_context);
204
205 // Paint an opaque round rect covering the whole area (leaving the extreme
206 // corners transparent).
207 cairo_set_source_rgba(cairo_context, 1, 1, 1, 1);
208 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
209 AddRoundRectPath(cairo_context, current_width_, current_height_,
210 kCornerRadius);
211 cairo_fill(cairo_context);
212
213 cairo_destroy(cairo_context);
214 gdk_window_shape_combine_mask(widget->window, shape_mask, 0, 0);
215 g_object_unref(shape_mask);
216
217 // Create a full-color pixmap for the window background image.
218 GdkPixmap* background = gdk_pixmap_new(NULL, current_width_, current_height_,
219 24);
220 cairo_context = gdk_cairo_create(background);
221
222 // Paint the whole bitmap one color.
223 cairo_set_source_rgb(cairo_context, 0.91, 0.91, 0.91);
224 cairo_paint(cairo_context);
225
226 // Paint the round-rectangle edge.
227 cairo_set_source_rgb(cairo_context, 0.13, 0.69, 0.11);
228 cairo_set_line_width(cairo_context, 6);
229 AddRoundRectPath(cairo_context, current_width_, current_height_,
230 kCornerRadius);
231 cairo_stroke(cairo_context);
232
233 // Render the window-gripper. In order for a straight line to light up
234 // single pixels, Cairo requires the coordinates to have fractional
235 // components of 0.5 (so the "/ 2" is a deliberate integer division).
236 double gripper_top = current_height_ / 2 - 10.5;
237 double gripper_bottom = current_height_ / 2 + 10.5;
238 cairo_set_line_width(cairo_context, 1);
239
240 double x = 12.5;
241 cairo_set_source_rgb(cairo_context, 0.70, 0.70, 0.70);
242 cairo_move_to(cairo_context, x, gripper_top);
243 cairo_line_to(cairo_context, x, gripper_bottom);
244 cairo_stroke(cairo_context);
245 x += 3;
246 cairo_move_to(cairo_context, x, gripper_top);
247 cairo_line_to(cairo_context, x, gripper_bottom);
248 cairo_stroke(cairo_context);
249
250 x -= 2;
251 cairo_set_source_rgb(cairo_context, 0.97, 0.97, 0.97);
252 cairo_move_to(cairo_context, x, gripper_top);
253 cairo_line_to(cairo_context, x, gripper_bottom);
254 cairo_stroke(cairo_context);
255 x += 3;
256 cairo_move_to(cairo_context, x, gripper_top);
257 cairo_line_to(cairo_context, x, gripper_bottom);
258 cairo_stroke(cairo_context);
259
260 cairo_destroy(cairo_context);
261
262 gdk_window_set_back_pixmap(widget->window, background, FALSE);
263 g_object_unref(background);
264 gdk_window_invalidate_rect(widget->window, NULL, TRUE);
265
266 return FALSE;
267 }
268
269 gboolean DisconnectWindowLinux::OnButtonPress(GtkWidget* widget,
270 GdkEventButton* event) {
271 gtk_window_begin_move_drag(GTK_WINDOW(disconnect_window_),
272 event->button,
273 event->x_root,
274 event->y_root,
275 event->time);
276 return FALSE;
277 }
278
279 scoped_ptr<DisconnectWindow> DisconnectWindow::Create() {
280 return scoped_ptr<DisconnectWindow>(new DisconnectWindowLinux());
281 }
282
283 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/disconnect_window_gtk.cc ('k') | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698