]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/minifram.cpp
Hotkey fix for submenus.
[wxWidgets.git] / src / gtk / minifram.cpp
CommitLineData
b2b3ccc5
RR
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
83624f79
RR
17#include "gtk/gtk.h"
18#include "wx/gtk/win_gtk.h"
19
32a95f9f
RR
20#include "gdk/gdk.h"
21#include "gdk/gdkprivate.h"
22#include "gdk/gdkx.h"
23
acfd422a
RR
24//-----------------------------------------------------------------------------
25// idle system
26//-----------------------------------------------------------------------------
27
28extern void wxapp_install_idle_handler();
29extern bool g_isIdle;
30
32a95f9f
RR
31//-----------------------------------------------------------------------------
32// data
33//-----------------------------------------------------------------------------
34
35extern bool g_blockEventsOnDrag;
36extern bool g_blockEventsOnScroll;
37
b2b3ccc5 38//-----------------------------------------------------------------------------
32a95f9f
RR
39// local functions
40//-----------------------------------------------------------------------------
41
42/* draw XOR rectangle when moving mine frame around */
43
44static void DrawFrame( GtkWidget *widget, int x, int y, int w, int h )
45{
46 int org_x = 0;
47 int org_y = 0;
48 gdk_window_get_origin( widget->window, &org_x, &org_y );
49 x += org_x;
50 y += org_y;
51
52 GdkGC *gc = gdk_gc_new( GDK_ROOT_PARENT() );
53 gdk_gc_set_subwindow( gc, GDK_INCLUDE_INFERIORS );
54 gdk_gc_set_function( gc, GDK_INVERT );
55
56 gdk_draw_rectangle( GDK_ROOT_PARENT(), gc, FALSE, x, y, w, h );
57 gdk_gc_unref( gc );
58}
59
60//-----------------------------------------------------------------------------
61// "expose_event" of m_mainWidget
62//-----------------------------------------------------------------------------
63
64static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxFrame *win )
65{
acfd422a
RR
66 if (g_isIdle) wxapp_install_idle_handler();
67
a2053b27 68 if (!win->m_hasVMT) return;
32a95f9f
RR
69 if (gdk_event->count > 0) return;
70
71 gtk_draw_shadow( widget->style,
72 widget->window,
f03fc89f
VZ
73 GTK_STATE_NORMAL,
74 GTK_SHADOW_OUT,
75 0, 0,
a2053b27 76 win->m_width, win->m_height );
b9a535f5
RR
77
78 if (!win->m_title.IsEmpty() &&
f03fc89f
VZ
79 ((win->GetWindowStyle() & wxCAPTION) ||
80 (win->GetWindowStyle() & wxTINY_CAPTION_HORIZ) ||
81 (win->GetWindowStyle() & wxTINY_CAPTION_VERT)))
b9a535f5
RR
82 {
83 GdkGC *gc = gdk_gc_new( widget->window );
f03fc89f
VZ
84 GdkFont *font = wxSMALL_FONT->GetInternalFont(1.0);
85 int x = 2;
86 if (win->GetWindowStyle() & wxSYSTEM_MENU) x = 18;
87
b9a535f5 88 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
f03fc89f
VZ
89 gdk_draw_rectangle( widget->window, gc, TRUE,
90 x,
91 3,
a2053b27 92 win->m_width - 4 - x,
f03fc89f
VZ
93 font->ascent + font->descent+1 );
94
b9a535f5
RR
95 gdk_gc_set_foreground( gc, &widget->style->white );
96 gdk_draw_string( widget->window, font, gc,
f03fc89f
VZ
97 x+2,
98 3+font->ascent,
99 win->m_title.mb_str() );
100
b9a535f5
RR
101 gdk_gc_unref( gc );
102 }
32a95f9f
RR
103}
104
105//-----------------------------------------------------------------------------
106// "draw" of m_mainWidget
107//-----------------------------------------------------------------------------
108
109static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxFrame *win )
110{
acfd422a
RR
111 if (g_isIdle) wxapp_install_idle_handler();
112
a2053b27 113 if (!win->m_hasVMT) return;
32a95f9f
RR
114
115 gtk_draw_shadow( widget->style,
116 widget->window,
f03fc89f
VZ
117 GTK_STATE_NORMAL,
118 GTK_SHADOW_OUT,
119 0, 0,
a2053b27 120 win->m_width, win->m_height );
f03fc89f 121
b9a535f5 122 if (!win->m_title.IsEmpty() &&
f03fc89f
VZ
123 ((win->GetWindowStyle() & wxCAPTION) ||
124 (win->GetWindowStyle() & wxTINY_CAPTION_HORIZ) ||
125 (win->GetWindowStyle() & wxTINY_CAPTION_VERT)))
b9a535f5
RR
126 {
127 GdkGC *gc = gdk_gc_new( widget->window );
f03fc89f
VZ
128 GdkFont *font = wxSMALL_FONT->GetInternalFont(1.0);
129 int x = 2;
130 if (win->GetWindowStyle() & wxSYSTEM_MENU) x = 17;
131
b9a535f5 132 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
f03fc89f
VZ
133 gdk_draw_rectangle( widget->window, gc, TRUE,
134 x,
135 3,
a2053b27 136 win->m_width - 4 - x,
f03fc89f
VZ
137 font->ascent + font->descent+1 );
138
b9a535f5
RR
139 gdk_gc_set_foreground( gc, &widget->style->white );
140 gdk_draw_string( widget->window, font, gc,
f03fc89f
VZ
141 x+2,
142 3+font->ascent,
143 win->m_title.mb_str() );
144
b9a535f5
RR
145 gdk_gc_unref( gc );
146 }
32a95f9f
RR
147}
148
149//-----------------------------------------------------------------------------
150// "button_press_event" of m_mainWidget
151//-----------------------------------------------------------------------------
152
153static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
154{
acfd422a
RR
155 if (g_isIdle) wxapp_install_idle_handler();
156
a2053b27 157 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
158 if (g_blockEventsOnDrag) return TRUE;
159 if (g_blockEventsOnScroll) return TRUE;
160
161 if (win->m_isDragging) return TRUE;
162
163 gdk_pointer_grab( widget->window, FALSE,
164 (GdkEventMask)
165 (GDK_BUTTON_PRESS_MASK |
166 GDK_BUTTON_RELEASE_MASK |
f03fc89f 167 GDK_POINTER_MOTION_MASK |
32a95f9f 168 GDK_POINTER_MOTION_HINT_MASK |
f03fc89f 169 GDK_BUTTON_MOTION_MASK |
32a95f9f
RR
170 GDK_BUTTON1_MOTION_MASK),
171 (GdkWindow *) NULL,
172 (GdkCursor *) NULL,
173 GDK_CURRENT_TIME );
f03fc89f 174
32a95f9f
RR
175 win->m_diffX = (int)gdk_event->x;
176 win->m_diffY = (int)gdk_event->y;
a2053b27 177 DrawFrame( widget, 0, 0, win->m_width, win->m_height );
32a95f9f
RR
178 win->m_oldX = 0;
179 win->m_oldY = 0;
180
181 win->m_isDragging = TRUE;
182
183 return TRUE;
184}
185
186//-----------------------------------------------------------------------------
187// "button_release_event" of m_mainWidget
188//-----------------------------------------------------------------------------
189
190static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
191{
acfd422a
RR
192 if (g_isIdle) wxapp_install_idle_handler();
193
a2053b27 194 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
195 if (g_blockEventsOnDrag) return TRUE;
196 if (g_blockEventsOnScroll) return TRUE;
197
198 if (!win->m_isDragging) return TRUE;
199
200 win->m_isDragging = FALSE;
201
202 int x = (int)gdk_event->x;
203 int y = (int)gdk_event->y;
204
a2053b27 205 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
32a95f9f
RR
206 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
207 int org_x = 0;
208 int org_y = 0;
209 gdk_window_get_origin( widget->window, &org_x, &org_y );
210 x += org_x - win->m_diffX;
211 y += org_y - win->m_diffY;
121a3581
RR
212 win->m_x = x;
213 win->m_y = y;
a2053b27 214 gtk_widget_set_uposition( win->m_widget, x, y );
32a95f9f
RR
215
216 return TRUE;
217}
218
219//-----------------------------------------------------------------------------
220// "motion_notify_event" of m_mainWidget
221//-----------------------------------------------------------------------------
222
223static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
224{
acfd422a
RR
225 if (g_isIdle) wxapp_install_idle_handler();
226
a2053b27 227 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
228 if (g_blockEventsOnDrag) return TRUE;
229 if (g_blockEventsOnScroll) return TRUE;
230
231 if (!win->m_isDragging) return TRUE;
232
233 if (gdk_event->is_hint)
234 {
235 int x = 0;
236 int y = 0;
237 GdkModifierType state;
238 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
239 gdk_event->x = x;
240 gdk_event->y = y;
241 gdk_event->state = state;
242 }
243
a2053b27 244 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
32a95f9f
RR
245 win->m_oldX = (int)gdk_event->x - win->m_diffX;
246 win->m_oldY = (int)gdk_event->y - win->m_diffY;
a2053b27 247 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
32a95f9f
RR
248
249 return TRUE;
250}
251
252//-----------------------------------------------------------------------------
253// "clicked" of X system button
b2b3ccc5
RR
254//-----------------------------------------------------------------------------
255
256static void gtk_button_clicked_callback( GtkWidget *WXUNUSED(widget), wxMiniFrame *mf )
257{
acfd422a
RR
258 if (g_isIdle) wxapp_install_idle_handler();
259
b2b3ccc5
RR
260 mf->Close();
261}
262
263//-----------------------------------------------------------------------------
264// wxMiniFrame
265//-----------------------------------------------------------------------------
266
b2b3ccc5
RR
267IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
268
269bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
270 const wxPoint &pos, const wxSize &size,
271 long style, const wxString &name )
272{
273 style = style | wxSIMPLE_BORDER;
b9a535f5
RR
274
275 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
276 m_miniTitle = 13;
f03fc89f 277
b2b3ccc5 278 m_miniEdge = 3;
b2b3ccc5
RR
279 m_isDragging = FALSE;
280 m_oldX = -1;
281 m_oldY = -1;
282 m_diffX = 0;
283 m_diffY = 0;
284
285 wxFrame::Create( parent, id, title, pos, size, style, name );
286
b9a535f5
RR
287 if ((style & wxSYSTEM_MENU) &&
288 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
289 {
290 GtkWidget *close_button = gtk_button_new_with_label( "x" );
b2b3ccc5 291
fdd3ed7a 292 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
f03fc89f
VZ
293 close_button,
294 4, 4, 12, 11 );
b2b3ccc5 295
b9a535f5 296 gtk_widget_show( close_button );
b2b3ccc5 297
b9a535f5
RR
298 gtk_signal_connect( GTK_OBJECT(close_button), "clicked",
299 GTK_SIGNAL_FUNC(gtk_button_clicked_callback), (gpointer*)this );
300 }
b2b3ccc5 301
32a95f9f
RR
302 /* these are called when the borders are drawn */
303 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
304 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
b2b3ccc5 305
32a95f9f
RR
306 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
307 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
308
309 /* these are required for dragging the mini frame around */
310 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_press_event",
311 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
b2b3ccc5 312
32a95f9f
RR
313 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_release_event",
314 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
b2b3ccc5 315
32a95f9f
RR
316 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "motion_notify_event",
317 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
b2b3ccc5 318
32a95f9f 319 return TRUE;
b2b3ccc5 320}