1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/minifram.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
15 #include "wx/minifram.h"
18 #include "wx/settings.h"
19 #include "wx/dcclient.h"
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 extern bool g_blockEventsOnDrag
;
31 extern bool g_blockEventsOnScroll
;
32 extern GtkWidget
*wxGetRootWindow();
34 //-----------------------------------------------------------------------------
35 // "expose_event" of m_mainWidget
36 //-----------------------------------------------------------------------------
38 // StepColour() it a utility function that simply darkens
39 // or lightens a color, based on the specified percentage
40 static wxColor
StepColour(const wxColor
& c
, int percent
)
42 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
43 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
44 (unsigned char)wxMin((g
*percent
)/100,255),
45 (unsigned char)wxMin((b
*percent
)/100,255));
48 static wxColor
LightContrastColour(const wxColour
& c
)
52 // if the color is especially dark, then
53 // make the contrast even lighter
54 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
57 return StepColour(c
, amount
);
61 static gboolean
gtk_window_own_expose_callback(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxMiniFrame
* win
)
63 if (!win
->m_hasVMT
|| gdk_event
->count
> 0)
66 GtkPizza
*pizza
= GTK_PIZZA(widget
);
68 gtk_paint_shadow (widget
->style
,
72 NULL
, NULL
, NULL
, // FIXME: No clipping?
74 win
->m_width
, win
->m_height
);
76 int style
= win
->GetWindowStyle();
80 dc
.m_window
= pizza
->bin_window
;
82 if (style
& wxRESIZE_BORDER
)
84 dc
.SetBrush( *wxGREY_BRUSH
);
85 dc
.SetPen( *wxTRANSPARENT_PEN
);
86 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
89 if (!win
->GetTitle().empty() &&
90 ((style
& wxCAPTION
) ||
91 (style
& wxTINY_CAPTION_HORIZ
) ||
92 (style
& wxTINY_CAPTION_VERT
)))
94 dc
.SetFont( *wxSMALL_FONT
);
95 int height
= dc
.GetCharHeight();
97 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
99 dc
.SetPen( *wxTRANSPARENT_PEN
);
100 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
);
102 dc
.SetTextForeground( *wxWHITE
);
103 dc
.DrawText( win
->GetTitle(), 6, 3 );
105 if (style
& wxCLOSE_BOX
)
106 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 2, true );
112 //-----------------------------------------------------------------------------
113 // "button_press_event" of m_mainWidget
114 //-----------------------------------------------------------------------------
117 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
119 if (!win
->m_hasVMT
) return FALSE
;
120 if (g_blockEventsOnDrag
) return TRUE
;
121 if (g_blockEventsOnScroll
) return TRUE
;
123 if (win
->m_isDragging
) return TRUE
;
125 GtkPizza
*pizza
= GTK_PIZZA(widget
);
126 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
128 int style
= win
->GetWindowStyle();
130 int y
= (int)gdk_event
->y
;
131 int x
= (int)gdk_event
->x
;
133 if ((style
& wxRESIZE_BORDER
) &&
134 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
136 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
138 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
142 gdk_window_get_origin( source
, &org_x
, &org_y
);
144 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
145 GDK_WINDOW_EDGE_SOUTH_EAST
,
154 if ((style
& wxCLOSE_BOX
) &&
155 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
157 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
165 dc
.SetFont( *wxSMALL_FONT
);
166 int height
= dc
.GetCharHeight() + 1;
169 if (y
> height
) return TRUE
;
171 gdk_window_raise( win
->m_widget
->window
);
173 gdk_pointer_grab( widget
->window
, FALSE
,
175 (GDK_BUTTON_PRESS_MASK
|
176 GDK_BUTTON_RELEASE_MASK
|
177 GDK_POINTER_MOTION_MASK
|
178 GDK_POINTER_MOTION_HINT_MASK
|
179 GDK_BUTTON_MOTION_MASK
|
180 GDK_BUTTON1_MOTION_MASK
),
183 (unsigned int) GDK_CURRENT_TIME
);
190 win
->m_isDragging
= true;
196 //-----------------------------------------------------------------------------
197 // "button_release_event" of m_mainWidget
198 //-----------------------------------------------------------------------------
201 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
203 if (!win
->m_hasVMT
) return FALSE
;
204 if (g_blockEventsOnDrag
) return TRUE
;
205 if (g_blockEventsOnScroll
) return TRUE
;
207 if (!win
->m_isDragging
) return TRUE
;
209 win
->m_isDragging
= false;
211 int x
= (int)gdk_event
->x
;
212 int y
= (int)gdk_event
->y
;
214 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
217 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
218 x
+= org_x
- win
->m_diffX
;
219 y
+= org_y
- win
->m_diffY
;
222 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
228 //-----------------------------------------------------------------------------
229 // "leave_notify_event" of m_mainWidget
230 //-----------------------------------------------------------------------------
234 gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxMiniFrame
*win
)
236 if (!win
->m_hasVMT
) return FALSE
;
237 if (g_blockEventsOnDrag
) return FALSE
;
239 gdk_window_set_cursor( widget
->window
, NULL
);
245 //-----------------------------------------------------------------------------
246 // "motion_notify_event" of m_mainWidget
247 //-----------------------------------------------------------------------------
251 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
253 if (!win
->m_hasVMT
) return FALSE
;
254 if (g_blockEventsOnDrag
) return TRUE
;
255 if (g_blockEventsOnScroll
) return TRUE
;
257 if (gdk_event
->is_hint
)
261 GdkModifierType state
;
262 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
265 gdk_event
->state
= state
;
268 int style
= win
->GetWindowStyle();
270 int x
= (int)gdk_event
->x
;
271 int y
= (int)gdk_event
->y
;
273 if (!win
->m_isDragging
)
275 if (style
& wxRESIZE_BORDER
)
277 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
278 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
280 gdk_window_set_cursor( widget
->window
, NULL
);
285 win
->m_oldX
= x
- win
->m_diffX
;
286 win
->m_oldY
= y
- win
->m_diffY
;
290 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
291 x
+= org_x
- win
->m_diffX
;
292 y
+= org_y
- win
->m_diffY
;
295 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
302 //-----------------------------------------------------------------------------
304 //-----------------------------------------------------------------------------
306 static unsigned char close_bits
[]={
307 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
308 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
309 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
312 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
314 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
315 const wxPoint
&pos
, const wxSize
&size
,
316 long style
, const wxString
&name
)
318 style
= style
| wxCAPTION
;
320 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
323 if (style
& wxRESIZE_BORDER
)
327 m_isDragging
= false;
333 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
335 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
337 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
340 if ((style
& wxCLOSE_BOX
) &&
341 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
343 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
344 img
.Replace(0,0,0,123,123,123);
345 img
.SetMaskColour(123,123,123);
346 m_closeButton
= wxBitmap( img
);
349 /* these are called when the borders are drawn */
350 g_signal_connect (m_mainWidget
, "expose_event",
351 G_CALLBACK (gtk_window_own_expose_callback
), this );
353 /* these are required for dragging the mini frame around */
354 g_signal_connect (m_mainWidget
, "button_press_event",
355 G_CALLBACK (gtk_window_button_press_callback
), this);
356 g_signal_connect (m_mainWidget
, "button_release_event",
357 G_CALLBACK (gtk_window_button_release_callback
), this);
358 g_signal_connect (m_mainWidget
, "motion_notify_event",
359 G_CALLBACK (gtk_window_motion_notify_callback
), this);
360 g_signal_connect (m_mainWidget
, "leave_notify_event",
361 G_CALLBACK (gtk_window_leave_callback
), this);
365 void wxMiniFrame::SetTitle( const wxString
&title
)
367 wxFrame::SetTitle( title
);
369 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
370 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
373 #endif // wxUSE_MINIFRAME