mini frame rewrite (titlebar still missing)
[wxWidgets.git] / src / gtk / minifram.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: minifram.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "minifram.h"
12 #endif
13
14 #include "wx/minifram.h"
15 #include "wx/dcscreen.h"
16
17 #include "gtk/gtk.h"
18 #include "wx/gtk/win_gtk.h"
19
20 #include "gdk/gdk.h"
21 #include "gdk/gdkprivate.h"
22 #include "gdk/gdkx.h"
23
24 //-----------------------------------------------------------------------------
25 // data
26 //-----------------------------------------------------------------------------
27
28 extern bool g_blockEventsOnDrag;
29 extern bool g_blockEventsOnScroll;
30
31 //-----------------------------------------------------------------------------
32 // local functions
33 //-----------------------------------------------------------------------------
34
35 /* draw XOR rectangle when moving mine frame around */
36
37 static void DrawFrame( GtkWidget *widget, int x, int y, int w, int h )
38 {
39 int org_x = 0;
40 int org_y = 0;
41 gdk_window_get_origin( widget->window, &org_x, &org_y );
42 x += org_x;
43 y += org_y;
44
45 GdkGC *gc = gdk_gc_new( GDK_ROOT_PARENT() );
46 gdk_gc_set_subwindow( gc, GDK_INCLUDE_INFERIORS );
47 gdk_gc_set_function( gc, GDK_INVERT );
48
49 gdk_draw_rectangle( GDK_ROOT_PARENT(), gc, FALSE, x, y, w, h );
50 gdk_gc_unref( gc );
51 }
52
53 //-----------------------------------------------------------------------------
54 // "expose_event" of m_mainWidget
55 //-----------------------------------------------------------------------------
56
57 static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxFrame *win )
58 {
59 if (!win->HasVMT()) return;
60 if (gdk_event->count > 0) return;
61
62 gtk_draw_shadow( widget->style,
63 widget->window,
64 GTK_STATE_NORMAL,
65 GTK_SHADOW_OUT,
66 0, 0,
67 win->m_width, win->m_height );
68 }
69
70 //-----------------------------------------------------------------------------
71 // "draw" of m_mainWidget
72 //-----------------------------------------------------------------------------
73
74 static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxFrame *win )
75 {
76 if (!win->HasVMT()) return;
77
78 gtk_draw_shadow( widget->style,
79 widget->window,
80 GTK_STATE_NORMAL,
81 GTK_SHADOW_OUT,
82 0, 0,
83 win->m_width, win->m_height );
84 }
85
86 //-----------------------------------------------------------------------------
87 // "button_press_event" of m_mainWidget
88 //-----------------------------------------------------------------------------
89
90 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
91 {
92 if (!win->HasVMT()) return FALSE;
93 if (g_blockEventsOnDrag) return TRUE;
94 if (g_blockEventsOnScroll) return TRUE;
95
96 if (win->m_isDragging) return TRUE;
97
98 gdk_pointer_grab( widget->window, FALSE,
99 (GdkEventMask)
100 (GDK_BUTTON_PRESS_MASK |
101 GDK_BUTTON_RELEASE_MASK |
102 GDK_POINTER_MOTION_MASK |
103 GDK_POINTER_MOTION_HINT_MASK |
104 GDK_BUTTON_MOTION_MASK |
105 GDK_BUTTON1_MOTION_MASK),
106 (GdkWindow *) NULL,
107 (GdkCursor *) NULL,
108 GDK_CURRENT_TIME );
109
110 win->m_diffX = (int)gdk_event->x;
111 win->m_diffY = (int)gdk_event->y;
112 DrawFrame( widget, 0, 0, win->m_width, win->m_height );
113 win->m_oldX = 0;
114 win->m_oldY = 0;
115
116 win->m_isDragging = TRUE;
117
118 return TRUE;
119 }
120
121 //-----------------------------------------------------------------------------
122 // "button_release_event" of m_mainWidget
123 //-----------------------------------------------------------------------------
124
125 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
126 {
127 if (!win->HasVMT()) return FALSE;
128 if (g_blockEventsOnDrag) return TRUE;
129 if (g_blockEventsOnScroll) return TRUE;
130
131 if (!win->m_isDragging) return TRUE;
132
133 win->m_isDragging = FALSE;
134
135 int x = (int)gdk_event->x;
136 int y = (int)gdk_event->y;
137
138 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
139 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
140 int org_x = 0;
141 int org_y = 0;
142 gdk_window_get_origin( widget->window, &org_x, &org_y );
143 x += org_x - win->m_diffX;
144 y += org_y - win->m_diffY;
145 win->m_x = x;
146 win->m_y = y;
147 gtk_widget_set_uposition( win->m_widget, x, y );
148
149 return TRUE;
150 }
151
152 //-----------------------------------------------------------------------------
153 // "motion_notify_event" of m_mainWidget
154 //-----------------------------------------------------------------------------
155
156 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
157 {
158 if (!win->HasVMT()) return FALSE;
159 if (g_blockEventsOnDrag) return TRUE;
160 if (g_blockEventsOnScroll) return TRUE;
161
162 if (!win->m_isDragging) return TRUE;
163
164 if (gdk_event->is_hint)
165 {
166 int x = 0;
167 int y = 0;
168 GdkModifierType state;
169 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
170 gdk_event->x = x;
171 gdk_event->y = y;
172 gdk_event->state = state;
173 }
174
175 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
176 win->m_oldX = (int)gdk_event->x - win->m_diffX;
177 win->m_oldY = (int)gdk_event->y - win->m_diffY;
178 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
179
180 return TRUE;
181 }
182
183 //-----------------------------------------------------------------------------
184 // "clicked" of X system button
185 //-----------------------------------------------------------------------------
186
187 static void gtk_button_clicked_callback( GtkWidget *WXUNUSED(widget), wxMiniFrame *mf )
188 {
189 mf->Close();
190 }
191
192 //-----------------------------------------------------------------------------
193 // wxMiniFrame
194 //-----------------------------------------------------------------------------
195
196 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
197
198 bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
199 const wxPoint &pos, const wxSize &size,
200 long style, const wxString &name )
201 {
202 style = style | wxSIMPLE_BORDER;
203
204 m_miniEdge = 3;
205 m_miniTitle = 13;
206 m_isDragging = FALSE;
207 m_oldX = -1;
208 m_oldY = -1;
209 m_diffX = 0;
210 m_diffY = 0;
211
212 wxFrame::Create( parent, id, title, pos, size, style, name );
213
214 GtkWidget *close_button = gtk_button_new_with_label( "x" );
215
216 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget), close_button, 4, 4 );
217 gtk_widget_set_usize( close_button, 12, 11 );
218
219 gtk_widget_show( close_button );
220
221 gtk_signal_connect( GTK_OBJECT(close_button), "clicked",
222 GTK_SIGNAL_FUNC(gtk_button_clicked_callback), (gpointer*)this );
223
224 /* these are called when the borders are drawn */
225 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
226 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
227
228 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
229 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
230
231 /* these are required for dragging the mini frame around */
232 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_press_event",
233 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
234
235 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_release_event",
236 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
237
238 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "motion_notify_event",
239 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
240
241 return TRUE;
242 }