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