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 <gtk/gtk.h> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/gfx/platform_canvas_linux.h" |
| 11 #include "base/gfx/platform_device_linux.h" |
| 12 #include "base/gfx/bitmap_platform_device_linux.h" |
| 13 #include "webkit/glue/webinputevent.h" |
| 14 #include "webkit/glue/webwidget.h" |
8 | 15 |
9 WebWidgetHost::WebWidgetHost() { | 16 namespace { |
10 NOTIMPLEMENTED(); | 17 |
| 18 // ----------------------------------------------------------------------------- |
| 19 // Callback functions to proxy to host... |
| 20 |
| 21 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 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 gboolean DestroyEvent(GtkWidget* widget, GdkEvent* event, gpointer userdata) { |
| 38 WebWidgetHost* host = (WebWidgetHost* ) userdata; |
| 39 DLOG(INFO) << " -- Destroy"; |
| 40 host->WindowDestroyed(); |
| 41 return FALSE; |
| 42 } |
| 43 |
| 44 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 gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus, gpointer userdata) { |
| 54 WebWidgetHost* host = (WebWidgetHost* ) userdata; |
| 55 host->webwidget()->SetFocus(true); |
| 56 return FALSE; |
| 57 } |
| 58 |
| 59 gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus, gpointer userdata) { |
| 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); |
11 } | 107 } |
12 | 108 |
13 WebWidgetHost::~WebWidgetHost() { | 109 WebWidgetHost::~WebWidgetHost() { |
14 NOTIMPLEMENTED(); | 110 webwidget_->Close(); |
| 111 webwidget_->Release(); |
15 } | 112 } |
| 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 |