OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "webkit/tools/test_shell/webwidget_host.h" | 5 #include "webkit/tools/test_shell/webwidget_host.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/gfx/platform_canvas_linux.h" | |
9 #include "base/gfx/platform_device_linux.h" | |
10 #include "base/gfx/bitmap_platform_device_linux.h" | |
11 #include "webkit/glue/webinputevent.h" | |
12 #include "webkit/glue/webwidget.h" | |
13 | 8 |
14 #include <gtk/gtk.h> | 9 WebWidgetHost::WebWidgetHost() { |
15 | 10 NOTIMPLEMENTED(); |
16 namespace { | |
17 | |
18 // ----------------------------------------------------------------------------- | |
19 // Callback functions to proxy to host... | |
20 | |
21 static gboolean configureEvent(GtkWidget* widget, GdkEventConfigure* config, | |
22 gpointer userdata) { | |
23 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
24 DLOG(INFO) << " -- Resize " << config->width << " " << config->height; | |
25 host->Resize(gfx::Size(config->width, config->height)); | |
26 return FALSE; | |
27 } | |
28 | |
29 static gboolean exposeEvent(GtkWidget* widget, GdkEventExpose* expose, | |
30 gpointer userdata) { | |
31 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
32 DLOG(INFO) << " -- Expose"; | |
33 host->Paint(); | |
34 return FALSE; | |
35 } | |
36 | |
37 static gboolean destroyEvent(GtkWidget* widget, GdkEvent* event, gpointer userda
ta) { | |
38 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
39 DLOG(INFO) << " -- Destroy"; | |
40 host->WindowDestroyed(); | |
41 return FALSE; | |
42 } | |
43 | |
44 static gboolean keyPressEvent(GtkWidget* widget, GdkEventKey* event, | |
45 gpointer userdata) { | |
46 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
47 DLOG(INFO) << " -- Key press"; | |
48 WebKeyboardEvent wke(event); | |
49 host->webwidget()->HandleInputEvent(&wke); | |
50 return FALSE; | |
51 } | |
52 | |
53 static gboolean focusIn(GtkWidget* widget, GdkEventFocus* focus, gpointer userda
ta) { | |
54 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
55 host->webwidget()->SetFocus(true); | |
56 return FALSE; | |
57 } | |
58 | |
59 static gboolean focusOut(GtkWidget* widget, GdkEventFocus* focus, gpointer userd
ata) { | |
60 WebWidgetHost* host = (WebWidgetHost* ) userdata; | |
61 host->webwidget()->SetFocus(false); | |
62 return FALSE; | |
63 } | |
64 | |
65 } // anonymous namespace | |
66 | |
67 // ----------------------------------------------------------------------------- | |
68 | |
69 WebWidgetHost* WebWidgetHost::Create(gfx::WindowHandle box, | |
70 WebWidgetDelegate* delegate) { | |
71 WebWidgetHost* host = new WebWidgetHost(); | |
72 host->view_ = gtk_drawing_area_new(); | |
73 gtk_widget_add_events(host->view_, GDK_EXPOSURE_MASK | | |
74 GDK_POINTER_MOTION_MASK | | |
75 GDK_BUTTON_PRESS_MASK | | |
76 GDK_BUTTON_RELEASE_MASK | | |
77 GDK_KEY_PRESS_MASK | | |
78 GDK_KEY_RELEASE_MASK); | |
79 // TODO(agl): set GTK_CAN_FOCUS flag | |
80 host->webwidget_ = WebWidget::Create(delegate); | |
81 g_object_set_data(G_OBJECT(host->view_), "webwidgethost", host); | |
82 | |
83 g_signal_connect(host->view_, "configure-event", G_CALLBACK(configureEvent), h
ost); | |
84 g_signal_connect(host->view_, "expose-event", G_CALLBACK(exposeEvent), host); | |
85 g_signal_connect(host->view_, "destroy-event", G_CALLBACK(destroyEvent), host)
; | |
86 g_signal_connect(host->view_, "key-press-event", G_CALLBACK(keyPressEvent), ho
st); | |
87 g_signal_connect(host->view_, "focus-in-event", G_CALLBACK(focusIn), host); | |
88 g_signal_connect(host->view_, "focus-out-event", G_CALLBACK(focusOut), host); | |
89 | |
90 gtk_box_pack_start(GTK_BOX(box), host->view_, TRUE, TRUE, 0); | |
91 | |
92 return host; | |
93 } | |
94 | |
95 WebWidgetHost* FromWindow(gfx::WindowHandle view) { | |
96 const gpointer p = g_object_get_data(G_OBJECT(view), "webwidgethost"); | |
97 return (WebWidgetHost* ) p; | |
98 } | |
99 | |
100 WebWidgetHost::WebWidgetHost() | |
101 : view_(NULL), | |
102 webwidget_(NULL), | |
103 scroll_dx_(0), | |
104 scroll_dy_(0), | |
105 track_mouse_leave_(false) { | |
106 set_painting(false); | |
107 } | 11 } |
108 | 12 |
109 WebWidgetHost::~WebWidgetHost() { | 13 WebWidgetHost::~WebWidgetHost() { |
110 webwidget_->Close(); | 14 NOTIMPLEMENTED(); |
111 webwidget_->Release(); | |
112 } | 15 } |
113 | |
114 void WebWidgetHost::Resize(const gfx::Size &newsize) { | |
115 // The pixel buffer backing us is now the wrong size | |
116 canvas_.reset(); | |
117 | |
118 gtk_widget_set_size_request(GTK_WIDGET(view_), newsize.width(), newsize.height
()); | |
119 webwidget_->Resize(gfx::Size(newsize.width(), newsize.height())); | |
120 } | |
121 | |
122 void WebWidgetHost::Paint() { | |
123 gint width, height; | |
124 gtk_widget_get_size_request(GTK_WIDGET(view_), &width, &height); | |
125 | |
126 gfx::Rect client_rect(width, height); | |
127 | |
128 if (!canvas_.get()) { | |
129 paint_rect_ = client_rect; | |
130 canvas_.reset(new gfx::PlatformCanvas(width, height, true)); | |
131 if (!canvas_.get()) { | |
132 // memory allocation failed, we can't paint. | |
133 LOG(ERROR) << "Failed to allocate memory for " << width << "x" << height; | |
134 return; | |
135 } | |
136 } | |
137 | |
138 // This may result in more invalidation | |
139 webwidget_->Layout(); | |
140 | |
141 // TODO(agl): scrolling code | |
142 | |
143 // Paint the canvas if necessary. Allow painting to generate extra rects the | |
144 // first time we call it. This is necessary because some WebCore rendering | |
145 // objects update their layout only when painted. | |
146 | |
147 for (int i = 0; i < 2; ++i) { | |
148 paint_rect_ = client_rect.Intersect(paint_rect_); | |
149 if (!paint_rect_.IsEmpty()) { | |
150 gfx::Rect rect(paint_rect_); | |
151 paint_rect_ = gfx::Rect(); | |
152 | |
153 DLOG_IF(WARNING, i == 1) << "painting caused additional invalidations"; | |
154 PaintRect(rect); | |
155 } | |
156 } | |
157 DCHECK(paint_rect_.IsEmpty()); | |
158 | |
159 // BitBlit to the X server | |
160 gfx::PlatformDeviceLinux &platdev = canvas_->getTopPlatformDevice(); | |
161 gfx::BitmapPlatformDeviceLinux* const bitdev = | |
162 static_cast<gfx::BitmapPlatformDeviceLinux* >(&platdev); | |
163 LOG(INFO) << "Using pixel data at " << (void *) gdk_pixbuf_get_pixels(bitdev->
pixbuf()); | |
164 gdk_draw_pixbuf(view_->window, NULL, bitdev->pixbuf(), | |
165 0, 0, 0, 0, width, height, GDK_RGB_DITHER_NONE, 0, 0); | |
166 gdk_pixbuf_save(bitdev->pixbuf(), "output.png", "png", NULL, NULL); | |
167 } | |
168 | |
169 void WebWidgetHost::PaintRect(const gfx::Rect& rect) { | |
170 set_painting(true); | |
171 webwidget_->Paint(canvas_.get(), rect); | |
172 set_painting(false); | |
173 } | |
174 | |
175 // ----------------------------------------------------------------------------- | |
176 // This is called when the GTK window is destroyed. In the Windows code this | |
177 // deletes this object. Since it's only test_shell it probably doesn't matter | |
178 // that much. | |
179 // ----------------------------------------------------------------------------- | |
180 void WebWidgetHost::WindowDestroyed() { | |
181 delete this; | |
182 } | |
OLD | NEW |