1 /*
2 * widget.cc
3 * Copyright 2015 John Lindgren
4 *
5 * This file is part of Audacious.
6 *
7 * Audacious is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free Software
9 * Foundation, version 2 or version 3 of the License.
10 *
11 * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * Audacious. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The Audacious team does not consider modular code linking to Audacious or
19 * using our public API to be a derived work.
20 */
21
22 #include "widget.h"
23
24 typedef GtkWidget DrawingArea;
25 typedef GtkWidgetClass DrawingAreaClass;
26
G_DEFINE_TYPE(DrawingArea,drawing_area,GTK_TYPE_WIDGET)27 G_DEFINE_TYPE (DrawingArea, drawing_area, GTK_TYPE_WIDGET)
28
29 static void drawing_area_class_init (DrawingAreaClass *) {}
30
drawing_area_init(DrawingArea * widget)31 static void drawing_area_init (DrawingArea * widget)
32 {
33 gtk_widget_set_has_window ((GtkWidget *) widget, false);
34 }
35
drawing_area_new()36 static GtkWidget * drawing_area_new ()
37 {
38 return (GtkWidget *) g_object_new (drawing_area_get_type (), nullptr);
39 }
40
set_input(GtkWidget * widget)41 void Widget::set_input (GtkWidget * widget)
42 {
43 m_widget = widget;
44 g_signal_connect (widget, "destroy", (GCallback) Widget::destroy_cb, this);
45 g_signal_connect (widget, "key-press-event", (GCallback) Widget::keypress_cb, this);
46 g_signal_connect (widget, "button-press-event", (GCallback) Widget::button_press_cb, this);
47 g_signal_connect (widget, "button-release-event", (GCallback) Widget::button_release_cb, this);
48 g_signal_connect (widget, "scroll-event", (GCallback) Widget::scroll_cb, this);
49 g_signal_connect (widget, "motion-notify-event", (GCallback) Widget::motion_cb, this);
50 g_signal_connect (widget, "leave-notify-event", (GCallback) Widget::leave_cb, this);
51 g_signal_connect (widget, "delete-event", (GCallback) Widget::close_cb, this);
52 }
53
set_drawable(GtkWidget * widget)54 void Widget::set_drawable (GtkWidget * widget)
55 {
56 m_drawable = widget;
57 g_signal_connect (widget, "realize", (GCallback) Widget::realize_cb, this);
58 g_signal_connect (widget, "expose-event", (GCallback) Widget::draw_cb, this);
59
60 if (! m_widget)
61 {
62 m_widget = widget;
63 g_signal_connect (widget, "destroy", (GCallback) Widget::destroy_cb, this);
64 }
65 }
66
add_input(int width,int height,bool track_motion,bool drawable)67 void Widget::add_input (int width, int height, bool track_motion, bool drawable)
68 {
69 int events = GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK |
70 GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK;
71
72 if (track_motion)
73 events |= GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK;
74
75 GtkWidget * widget = gtk_event_box_new ();
76 gtk_event_box_set_visible_window ((GtkEventBox *) widget, false);
77 gtk_widget_set_size_request (widget, width * m_scale, height * m_scale);
78 gtk_widget_add_events (widget, events);
79 gtk_widget_show (widget);
80 set_input (widget);
81
82 if (drawable)
83 {
84 GtkWidget * area = drawing_area_new ();
85 gtk_container_add ((GtkContainer *) widget, area);
86 gtk_widget_show (area);
87 set_drawable (area);
88 }
89 }
90
add_drawable(int width,int height)91 void Widget::add_drawable (int width, int height)
92 {
93 GtkWidget * widget = drawing_area_new ();
94 gtk_widget_set_size_request (widget, width * m_scale, height * m_scale);
95 gtk_widget_show (widget);
96 set_drawable (widget);
97 }
98
draw_now()99 void Widget::draw_now ()
100 {
101 if (m_drawable && gtk_widget_is_drawable (m_drawable))
102 draw_cb (m_drawable, nullptr, this);
103 }
104
draw_cb(GtkWidget * widget,GdkEventExpose * event,Widget * me)105 gboolean Widget::draw_cb (GtkWidget * widget, GdkEventExpose * event, Widget * me)
106 {
107 cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
108
109 if (! gtk_widget_get_has_window (widget))
110 {
111 GtkAllocation alloc;
112 gtk_widget_get_allocation (widget, & alloc);
113 cairo_translate (cr, alloc.x, alloc.y);
114 cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
115 cairo_clip (cr);
116 }
117
118 if (me->m_scale != 1)
119 cairo_scale (cr, me->m_scale, me->m_scale);
120
121 me->draw (cr);
122
123 cairo_destroy (cr);
124 return false;
125 }
126