]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/minifram.cpp
Deallocate wxThreadSpecificInfo when wxThread ends.
[wxWidgets.git] / src / gtk1 / minifram.cpp
CommitLineData
b2b3ccc5 1/////////////////////////////////////////////////////////////////////////////
3cbab641 2// Name: src/gtk1/minifram.cpp
b2b3ccc5
RR
3// Purpose:
4// Author: Robert Roebling
b2b3ccc5 5// Copyright: (c) 1998 Robert Roebling
65571936 6// Licence: wxWindows licence
b2b3ccc5
RR
7/////////////////////////////////////////////////////////////////////////////
8
14f355c2
VS
9// For compilers that support precompilation, includes "wx.h".
10#include "wx/wxprec.h"
11
dcf924a3
RR
12#if wxUSE_MINIFRAME
13
11dbb4bf
WS
14#include "wx/minifram.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/dcscreen.h"
18#endif
b2b3ccc5 19
83624f79 20#include "gtk/gtk.h"
76c32e7b 21#include "wx/dcclient.h"
3cbab641
MR
22#include "wx/gtk1/win_gtk.h"
23#include "wx/gtk1/private.h"
10d30222 24#include "wx/gtk1/dcclient.h"
83624f79 25
5e7e9e1b
RR
26#include <gdk/gdk.h>
27#include <gdk/gdkprivate.h>
28#include <gdk/gdkx.h>
32a95f9f 29
acfd422a
RR
30//-----------------------------------------------------------------------------
31// idle system
32//-----------------------------------------------------------------------------
33
34extern void wxapp_install_idle_handler();
35extern bool g_isIdle;
36
32a95f9f
RR
37//-----------------------------------------------------------------------------
38// data
39//-----------------------------------------------------------------------------
40
8480b297
RR
41extern bool g_blockEventsOnDrag;
42extern bool g_blockEventsOnScroll;
c2fa61e8 43extern GtkWidget *wxGetRootWindow();
32a95f9f 44
b2b3ccc5 45//-----------------------------------------------------------------------------
32a95f9f
RR
46// local functions
47//-----------------------------------------------------------------------------
48
49/* draw XOR rectangle when moving mine frame around */
50
51static void DrawFrame( GtkWidget *widget, int x, int y, int w, int h )
52{
c2fa61e8 53 int org_x = 0;
32a95f9f
RR
54 int org_y = 0;
55 gdk_window_get_origin( widget->window, &org_x, &org_y );
56 x += org_x;
57 y += org_y;
58
59 GdkGC *gc = gdk_gc_new( GDK_ROOT_PARENT() );
60 gdk_gc_set_subwindow( gc, GDK_INCLUDE_INFERIORS );
61 gdk_gc_set_function( gc, GDK_INVERT );
c2fa61e8 62
32a95f9f
RR
63 gdk_draw_rectangle( GDK_ROOT_PARENT(), gc, FALSE, x, y, w, h );
64 gdk_gc_unref( gc );
65}
66
67//-----------------------------------------------------------------------------
68// "expose_event" of m_mainWidget
69//-----------------------------------------------------------------------------
70
865bb325 71extern "C" {
32a95f9f
RR
72static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxFrame *win )
73{
acfd422a
RR
74 if (g_isIdle) wxapp_install_idle_handler();
75
a2053b27 76 if (!win->m_hasVMT) return;
32a95f9f 77 if (gdk_event->count > 0) return;
c2fa61e8 78
da048e3d 79 GtkPizza *pizza = GTK_PIZZA(widget);
c2fa61e8
RD
80
81 gtk_draw_shadow( widget->style,
da048e3d 82 pizza->bin_window,
f03fc89f
VZ
83 GTK_STATE_NORMAL,
84 GTK_SHADOW_OUT,
85 0, 0,
a2053b27 86 win->m_width, win->m_height );
b9a535f5 87
340bfb43 88 if (!win->GetTitle().empty() &&
c2fa61e8 89 ((win->GetWindowStyle() & wxCAPTION) ||
7282b067 90 (win->GetWindowStyle() & wxTINY_CAPTION)))
b9a535f5 91 {
ba718523
RR
92 wxClientDC dc(win);
93 dc.SetFont( *wxSMALL_FONT );
94 int height = dc.GetCharHeight();
340bfb43 95
da048e3d 96 GdkGC *gc = gdk_gc_new( pizza->bin_window );
b9a535f5 97 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
c2fa61e8
RD
98 gdk_draw_rectangle( pizza->bin_window, gc, TRUE,
99 3,
100 3,
5d5b3a40 101 win->m_width - 7,
ba718523 102 height+1 );
b9a535f5 103 gdk_gc_unref( gc );
ba718523
RR
104
105 // Hack alert
5c33522f 106 static_cast<wxClientDCImpl *>(dc.GetImpl())->m_window = pizza->bin_window;
ba718523
RR
107 dc.SetTextForeground( *wxWHITE );
108 dc.DrawText( win->GetTitle(), 6, 3 );
b9a535f5 109 }
32a95f9f 110}
865bb325 111}
32a95f9f
RR
112
113//-----------------------------------------------------------------------------
114// "draw" of m_mainWidget
115//-----------------------------------------------------------------------------
116
865bb325 117extern "C" {
32a95f9f
RR
118static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxFrame *win )
119{
acfd422a
RR
120 if (g_isIdle) wxapp_install_idle_handler();
121
a2053b27 122 if (!win->m_hasVMT) return;
c2fa61e8 123
da048e3d 124 GtkPizza *pizza = GTK_PIZZA(widget);
c2fa61e8
RD
125
126 gtk_draw_shadow( widget->style,
da048e3d 127 pizza->bin_window,
f03fc89f
VZ
128 GTK_STATE_NORMAL,
129 GTK_SHADOW_OUT,
130 0, 0,
a2053b27 131 win->m_width, win->m_height );
c2fa61e8 132
340bfb43 133 if (!win->GetTitle().empty() &&
c2fa61e8 134 ((win->GetWindowStyle() & wxCAPTION) ||
7282b067 135 (win->GetWindowStyle() & wxTINY_CAPTION)))
b9a535f5 136 {
ba718523
RR
137 wxClientDC dc(win);
138 dc.SetFont( *wxSMALL_FONT );
139 int height = dc.GetCharHeight();
340bfb43 140
da048e3d 141 GdkGC *gc = gdk_gc_new( pizza->bin_window );
b9a535f5 142 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
c2fa61e8
RD
143 gdk_draw_rectangle( pizza->bin_window, gc, TRUE,
144 3,
5d5b3a40
RR
145 3,
146 win->m_width - 7,
ba718523 147 height+1 );
b9a535f5 148 gdk_gc_unref( gc );
ba718523
RR
149
150 // Hack alert
5c33522f 151 static_cast<wxClientDCImpl *>(dc.GetImpl())->m_window = pizza->bin_window;
ba718523
RR
152 dc.SetTextForeground( *wxWHITE );
153 dc.DrawText( win->GetTitle(), 6, 3 );
b9a535f5 154 }
32a95f9f 155}
865bb325 156}
32a95f9f
RR
157
158//-----------------------------------------------------------------------------
159// "button_press_event" of m_mainWidget
160//-----------------------------------------------------------------------------
161
865bb325 162extern "C" {
32a95f9f
RR
163static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
164{
acfd422a
RR
165 if (g_isIdle) wxapp_install_idle_handler();
166
a2053b27 167 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
168 if (g_blockEventsOnDrag) return TRUE;
169 if (g_blockEventsOnScroll) return TRUE;
170
171 if (win->m_isDragging) return TRUE;
172
2c990ec0
RR
173 GtkPizza *pizza = GTK_PIZZA(widget);
174 if (gdk_event->window != pizza->bin_window) return TRUE;
ba718523
RR
175
176 wxClientDC dc(win);
177 dc.SetFont( *wxSMALL_FONT );
178 int height = dc.GetCharHeight() + 1;
340bfb43 179
2c990ec0 180 if (gdk_event->y > height) return TRUE;
340bfb43 181
4dcaf11a 182 gdk_window_raise( win->m_widget->window );
c2fa61e8 183
32a95f9f
RR
184 gdk_pointer_grab( widget->window, FALSE,
185 (GdkEventMask)
186 (GDK_BUTTON_PRESS_MASK |
187 GDK_BUTTON_RELEASE_MASK |
f03fc89f 188 GDK_POINTER_MOTION_MASK |
32a95f9f 189 GDK_POINTER_MOTION_HINT_MASK |
f03fc89f 190 GDK_BUTTON_MOTION_MASK |
32a95f9f 191 GDK_BUTTON1_MOTION_MASK),
d3b9f782
VZ
192 NULL,
193 NULL,
7941ba11 194 (unsigned int) GDK_CURRENT_TIME );
c2fa61e8 195
32a95f9f
RR
196 win->m_diffX = (int)gdk_event->x;
197 win->m_diffY = (int)gdk_event->y;
a2053b27 198 DrawFrame( widget, 0, 0, win->m_width, win->m_height );
32a95f9f
RR
199 win->m_oldX = 0;
200 win->m_oldY = 0;
c2fa61e8 201
340bfb43 202 win->m_isDragging = true;
32a95f9f
RR
203
204 return TRUE;
205}
865bb325 206}
32a95f9f
RR
207
208//-----------------------------------------------------------------------------
209// "button_release_event" of m_mainWidget
210//-----------------------------------------------------------------------------
211
865bb325 212extern "C" {
32a95f9f
RR
213static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
214{
acfd422a
RR
215 if (g_isIdle) wxapp_install_idle_handler();
216
a2053b27 217 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
218 if (g_blockEventsOnDrag) return TRUE;
219 if (g_blockEventsOnScroll) return TRUE;
220
221 if (!win->m_isDragging) return TRUE;
c2fa61e8 222
11dbb4bf 223 win->m_isDragging = false;
c2fa61e8 224
32a95f9f
RR
225 int x = (int)gdk_event->x;
226 int y = (int)gdk_event->y;
c2fa61e8 227
a2053b27 228 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
13111b2a 229 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
c2fa61e8 230 int org_x = 0;
32a95f9f
RR
231 int org_y = 0;
232 gdk_window_get_origin( widget->window, &org_x, &org_y );
233 x += org_x - win->m_diffX;
234 y += org_y - win->m_diffY;
121a3581
RR
235 win->m_x = x;
236 win->m_y = y;
a2053b27 237 gtk_widget_set_uposition( win->m_widget, x, y );
32a95f9f
RR
238
239 return TRUE;
240}
865bb325 241}
32a95f9f
RR
242
243//-----------------------------------------------------------------------------
244// "motion_notify_event" of m_mainWidget
245//-----------------------------------------------------------------------------
246
865bb325 247extern "C" {
32a95f9f
RR
248static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
249{
acfd422a
RR
250 if (g_isIdle) wxapp_install_idle_handler();
251
a2053b27 252 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
253 if (g_blockEventsOnDrag) return TRUE;
254 if (g_blockEventsOnScroll) return TRUE;
255
256 if (!win->m_isDragging) return TRUE;
c2fa61e8 257
32a95f9f
RR
258 if (gdk_event->is_hint)
259 {
260 int x = 0;
261 int y = 0;
262 GdkModifierType state;
263 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
264 gdk_event->x = x;
265 gdk_event->y = y;
266 gdk_event->state = state;
267 }
268
a2053b27 269 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
32a95f9f
RR
270 win->m_oldX = (int)gdk_event->x - win->m_diffX;
271 win->m_oldY = (int)gdk_event->y - win->m_diffY;
a2053b27 272 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
c2fa61e8 273
32a95f9f
RR
274 return TRUE;
275}
865bb325 276}
32a95f9f
RR
277
278//-----------------------------------------------------------------------------
279// "clicked" of X system button
b2b3ccc5
RR
280//-----------------------------------------------------------------------------
281
865bb325 282extern "C" {
b2b3ccc5
RR
283static void gtk_button_clicked_callback( GtkWidget *WXUNUSED(widget), wxMiniFrame *mf )
284{
acfd422a
RR
285 if (g_isIdle) wxapp_install_idle_handler();
286
b2b3ccc5
RR
287 mf->Close();
288}
865bb325 289}
b2b3ccc5
RR
290
291//-----------------------------------------------------------------------------
292// wxMiniFrame
293//-----------------------------------------------------------------------------
294
90350682 295static const char *cross_xpm[] = {
5d5b3a40
RR
296/* columns rows colors chars-per-pixel */
297"5 5 16 1",
298" c Gray0",
299". c #bf0000",
300"X c #00bf00",
301"o c #bfbf00",
302"O c #0000bf",
303"+ c #bf00bf",
304"@ c #00bfbf",
305"# c None",
306"$ c #808080",
307"% c Red",
308"& c Green",
309"* c Yellow",
310"= c Blue",
311"- c Magenta",
312"; c Cyan",
313": c Gray100",
314/* pixels */
315" ### ",
316"# # #",
317"## ##",
318"# # #",
319" ### ",
320};
321
b2b3ccc5
RR
322IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
323
324bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
325 const wxPoint &pos, const wxSize &size,
326 long style, const wxString &name )
327{
2c990ec0 328 style = style | wxCAPTION;
b9a535f5 329
7282b067 330 if ((style & wxCAPTION) || (style & wxTINY_CAPTION))
b9a535f5 331 m_miniTitle = 13;
c2fa61e8 332
b2b3ccc5 333 m_miniEdge = 3;
340bfb43 334 m_isDragging = false;
b2b3ccc5
RR
335 m_oldX = -1;
336 m_oldY = -1;
337 m_diffX = 0;
338 m_diffY = 0;
c2fa61e8 339
b2b3ccc5
RR
340 wxFrame::Create( parent, id, title, pos, size, style, name );
341
2c990ec0
RR
342 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)))
343 {
344 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
345 }
340bfb43 346
b9a535f5 347 if ((style & wxSYSTEM_MENU) &&
7282b067 348 ((style & wxCAPTION) || (style & wxTINY_CAPTION)))
b9a535f5 349 {
d3b9f782 350 GdkBitmap *mask = NULL;
90350682
VZ
351 GdkPixmap *pixmap = gdk_pixmap_create_from_xpm_d
352 (
353 wxGetRootWindow()->window,
354 &mask,
355 NULL,
356 (char **)cross_xpm
357 );
c2fa61e8 358
5d5b3a40
RR
359 GtkWidget *pw = gtk_pixmap_new( pixmap, mask );
360 gdk_bitmap_unref( mask );
361 gdk_pixmap_unref( pixmap );
362 gtk_widget_show( pw );
c2fa61e8 363
5d5b3a40
RR
364 GtkWidget *close_button = gtk_button_new();
365 gtk_container_add( GTK_CONTAINER(close_button), pw );
c2fa61e8
RD
366
367 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
368 close_button,
5d5b3a40 369 size.x-16, 4, 11, 11 );
c2fa61e8 370
b9a535f5 371 gtk_widget_show( close_button );
c2fa61e8 372
b9a535f5
RR
373 gtk_signal_connect( GTK_OBJECT(close_button), "clicked",
374 GTK_SIGNAL_FUNC(gtk_button_clicked_callback), (gpointer*)this );
375 }
c2fa61e8 376
32a95f9f
RR
377 /* these are called when the borders are drawn */
378 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
379 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
b2b3ccc5 380
32a95f9f
RR
381 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
382 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
c2fa61e8 383
32a95f9f
RR
384 /* these are required for dragging the mini frame around */
385 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_press_event",
386 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
b2b3ccc5 387
32a95f9f
RR
388 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_release_event",
389 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
b2b3ccc5 390
32a95f9f
RR
391 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "motion_notify_event",
392 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
b2b3ccc5 393
340bfb43 394 return true;
b2b3ccc5 395}
dcf924a3 396
400be137
RR
397void wxMiniFrame::SetTitle( const wxString &title )
398{
399 wxFrame::SetTitle( title );
340bfb43 400
d3b9f782 401 gtk_widget_draw( m_mainWidget, NULL );
400be137
RR
402}
403
11dbb4bf 404#endif // wxUSE_MINIFRAME