2 * Copyright (C) 2006 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
25 #include "swfdec_widget.h"
28 G_DEFINE_TYPE (SwfdecWidget
, swfdec_widget
, GTK_TYPE_WIDGET
)
32 swfdec_widget_motion_notify (GtkWidget
*gtkwidget
, GdkEventMotion
*event
)
34 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
37 gdk_window_get_pointer (gtkwidget
->window
, &x
, &y
, NULL
);
39 swfdec_player_handle_mouse (widget
->player
,
40 x
/ widget
->real_scale
, y
/ widget
->real_scale
, widget
->button
);
46 swfdec_widget_leave_notify (GtkWidget
*gtkwidget
, GdkEventCrossing
*event
)
48 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
51 swfdec_player_handle_mouse (widget
->player
,
52 event
->x
/ widget
->real_scale
, event
->y
/ widget
->real_scale
, 0);
57 swfdec_widget_button_press (GtkWidget
*gtkwidget
, GdkEventButton
*event
)
59 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
61 if (event
->button
== 1) {
63 swfdec_player_handle_mouse (widget
->player
,
64 event
->x
/ widget
->real_scale
, event
->y
/ widget
->real_scale
, 1);
70 swfdec_widget_button_release (GtkWidget
*gtkwidget
, GdkEventButton
*event
)
72 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
74 if (event
->button
== 1) {
76 swfdec_player_handle_mouse (widget
->player
,
77 event
->x
/ widget
->real_scale
, event
->y
/ widget
->real_scale
, 0);
83 swfdec_widget_expose (GtkWidget
*gtkwidget
, GdkEventExpose
*event
)
85 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
88 cairo_surface_t
*surface
= NULL
;
90 if (event
->window
!= gtkwidget
->window
)
93 if (!widget
->use_image
) {
94 cr
= gdk_cairo_create (gtkwidget
->window
);
96 surface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
,
97 event
->area
.width
, event
->area
.height
);
98 cr
= cairo_create (surface
);
99 cairo_translate (cr
, -event
->area
.x
, -event
->area
.y
);
100 cairo_surface_destroy (surface
);
102 cairo_scale (cr
, widget
->real_scale
, widget
->real_scale
);
103 swfdec_rect_init (&rect
, event
->area
.x
/ widget
->real_scale
, event
->area
.y
/ widget
->real_scale
,
104 event
->area
.width
/ widget
->real_scale
, event
->area
.height
/ widget
->real_scale
);
105 swfdec_player_render (widget
->player
, cr
, &rect
);
106 if (widget
->use_image
) {
107 cairo_t
*crw
= gdk_cairo_create (gtkwidget
->window
);
108 cairo_set_source_surface (crw
, surface
, event
->area
.x
, event
->area
.y
);
119 swfdec_widget_dispose (GObject
*object
)
121 SwfdecWidget
*widget
= SWFDEC_WIDGET (object
);
123 swfdec_widget_set_player (widget
, NULL
);
125 G_OBJECT_CLASS (swfdec_widget_parent_class
)->dispose (object
);
129 swfdec_widget_size_allocate (GtkWidget
*gtkwidget
, GtkAllocation
*allocation
)
133 SwfdecWidget
*widget
= SWFDEC_WIDGET (gtkwidget
);
135 gtkwidget
->allocation
= *allocation
;
137 swfdec_player_get_image_size (widget
->player
, &w
, &h
);
138 if (widget
->set_scale
> 0.0) {
139 scale
= widget
->set_scale
;
140 } else if (widget
->player
== NULL
) {
143 if (w
!= 0 && h
!= 0)
144 scale
= MIN ((double) allocation
->width
/ w
, (double) allocation
->height
/ h
);
148 w
= ceil (w
* scale
);
149 h
= ceil (h
* scale
);
150 if (w
> allocation
->width
)
151 w
= allocation
->width
;
152 if (h
> allocation
->height
)
153 h
= allocation
->height
;
155 if (GTK_WIDGET_REALIZED (gtkwidget
)) {
156 gdk_window_move_resize (gtkwidget
->window
,
157 allocation
->x
+ (allocation
->width
- w
) / 2,
158 allocation
->y
+ (allocation
->height
- h
) / 2,
161 widget
->real_scale
= scale
;
165 swfdec_widget_size_request (GtkWidget
*gtkwidget
, GtkRequisition
*req
)
168 SwfdecWidget
* widget
= SWFDEC_WIDGET (gtkwidget
);
170 if (widget
->player
== NULL
) {
171 req
->width
= req
->height
= 0;
173 swfdec_player_get_image_size (widget
->player
,
174 &req
->width
, &req
->height
);
176 if (widget
->set_scale
!= 0.0)
177 scale
= widget
->set_scale
;
180 req
->width
= ceil (req
->width
* scale
);
181 req
->height
= ceil (req
->height
* scale
);
185 swfdec_widget_update_cursor (SwfdecWidget
*widget
)
187 GdkWindow
*window
= GTK_WIDGET (widget
)->window
;
192 g_object_get (widget
->player
, "mouse-visible", &visible
, NULL
);
195 gdk_window_set_cursor (window
, NULL
);
199 GdkColor color
= { 0, 0, 0, 0 };
202 bitmap
= gdk_bitmap_create_from_data (window
, &data
, 1, 1);
205 cursor
= gdk_cursor_new_from_pixmap (bitmap
, bitmap
, &color
, &color
, 0, 0);
206 gdk_window_set_cursor (window
, cursor
);
207 gdk_cursor_unref (cursor
);
208 g_object_unref (bitmap
);
213 swfdec_widget_realize (GtkWidget
*widget
)
215 GdkWindowAttr attributes
;
216 gint attributes_mask
;
218 GTK_WIDGET_SET_FLAGS (widget
, GTK_REALIZED
);
220 attributes
.window_type
= GDK_WINDOW_CHILD
;
221 attributes
.x
= widget
->allocation
.x
;
222 attributes
.y
= widget
->allocation
.y
;
223 attributes
.width
= widget
->allocation
.width
;
224 attributes
.height
= widget
->allocation
.height
;
225 attributes
.wclass
= GDK_INPUT_OUTPUT
;
226 attributes
.event_mask
= gtk_widget_get_events (widget
);
227 attributes
.event_mask
|= GDK_EXPOSURE_MASK
|
228 GDK_BUTTON_PRESS_MASK
|
229 GDK_BUTTON_RELEASE_MASK
|
230 GDK_LEAVE_NOTIFY_MASK
|
231 GDK_POINTER_MOTION_MASK
|
232 GDK_POINTER_MOTION_HINT_MASK
;
234 attributes_mask
= GDK_WA_X
| GDK_WA_Y
;
236 widget
->window
= gdk_window_new (gtk_widget_get_parent_window (widget
),
237 &attributes
, attributes_mask
);
238 gdk_window_set_user_data (widget
->window
, widget
);
240 widget
->style
= gtk_style_attach (widget
->style
, widget
->window
);
242 if (SWFDEC_WIDGET (widget
)->player
) {
243 swfdec_widget_update_cursor (SWFDEC_WIDGET (widget
));
248 swfdec_widget_class_init (SwfdecWidgetClass
* g_class
)
250 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
251 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS (g_class
);
253 object_class
->dispose
= swfdec_widget_dispose
;
255 widget_class
->realize
= swfdec_widget_realize
;
256 widget_class
->size_request
= swfdec_widget_size_request
;
257 widget_class
->size_allocate
= swfdec_widget_size_allocate
;
258 widget_class
->expose_event
= swfdec_widget_expose
;
259 widget_class
->button_press_event
= swfdec_widget_button_press
;
260 widget_class
->button_release_event
= swfdec_widget_button_release
;
261 widget_class
->motion_notify_event
= swfdec_widget_motion_notify
;
262 widget_class
->leave_notify_event
= swfdec_widget_leave_notify
;
266 swfdec_widget_init (SwfdecWidget
* widget
)
268 widget
->real_scale
= 1.0;
272 swfdec_widget_invalidate_cb (SwfdecPlayer
*player
, const SwfdecRect
*invalid
, SwfdecWidget
*widget
)
274 GdkRectangle gdkrect
;
277 if (!GTK_WIDGET_REALIZED (widget
))
279 swfdec_rect_scale (&rect
, invalid
, widget
->real_scale
);
280 gdkrect
.x
= floor (rect
.x0
);
281 gdkrect
.y
= floor (rect
.y0
);
282 gdkrect
.width
= ceil (rect
.x1
) - gdkrect
.x
;
283 gdkrect
.height
= ceil (rect
.y1
) - gdkrect
.y
;
284 //g_print ("queing draw of %g %g %g %g\n", rect.x0, rect.y0, rect.x1, rect.y1);
285 gdk_window_invalidate_rect (GTK_WIDGET (widget
)->window
, &gdkrect
, FALSE
);
289 swfdec_widget_notify_cb (SwfdecPlayer
*player
, GParamSpec
*pspec
, SwfdecWidget
*widget
)
291 if (g_str_equal (pspec
->name
, "mouse-visible")) {
292 swfdec_widget_update_cursor (widget
);
293 } else if (g_str_equal (pspec
->name
, "initialized")) {
294 gtk_widget_queue_resize (GTK_WIDGET (widget
));
299 swfdec_widget_set_player (SwfdecWidget
*widget
, SwfdecPlayer
*player
)
301 g_return_if_fail (SWFDEC_IS_WIDGET (widget
));
302 g_return_if_fail (player
== NULL
|| SWFDEC_IS_PLAYER (player
));
304 if (widget
->player
) {
305 g_signal_handlers_disconnect_by_func (widget
->player
, swfdec_widget_invalidate_cb
, widget
);
306 g_signal_handlers_disconnect_by_func (widget
->player
, swfdec_widget_notify_cb
, widget
);
307 g_object_unref (widget
->player
);
309 widget
->player
= player
;
311 g_signal_connect (player
, "invalidate", G_CALLBACK (swfdec_widget_invalidate_cb
), widget
);
312 g_signal_connect (player
, "notify", G_CALLBACK (swfdec_widget_notify_cb
), widget
);
313 g_object_ref (player
);
314 swfdec_widget_update_cursor (widget
);
316 if (GTK_WIDGET (widget
)->window
)
317 gdk_window_set_cursor (GTK_WIDGET (widget
)->window
, NULL
);
319 gtk_widget_queue_resize (GTK_WIDGET (widget
));
323 swfdec_widget_new (SwfdecPlayer
*player
)
325 SwfdecWidget
*widget
;
327 g_return_val_if_fail (player
== NULL
|| SWFDEC_IS_PLAYER (player
), NULL
);
329 widget
= g_object_new (SWFDEC_TYPE_WIDGET
, 0);
330 swfdec_widget_set_player (widget
, player
);
332 return GTK_WIDGET (widget
);
336 swfdec_widget_set_scale (SwfdecWidget
*widget
, double scale
)
338 g_return_if_fail (SWFDEC_IS_WIDGET (widget
));
339 g_return_if_fail (scale
>= 0.0);
341 widget
->set_scale
= scale
;
342 gtk_widget_queue_resize (GTK_WIDGET (widget
));
346 swfdec_widget_get_scale (SwfdecWidget
*widget
)
348 g_return_val_if_fail (SWFDEC_IS_WIDGET (widget
), 1.0);
350 return widget
->set_scale
;
354 swfdec_widget_set_use_image (SwfdecWidget
*widget
, gboolean use_image
)
356 g_return_if_fail (SWFDEC_IS_WIDGET (widget
));
358 widget
->use_image
= use_image
;
359 gtk_widget_queue_draw (GTK_WIDGET (widget
));
363 swfdec_widget_get_use_image (SwfdecWidget
*widget
)
365 g_return_val_if_fail (SWFDEC_IS_WIDGET (widget
), 1.0);
367 return widget
->use_image
;