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