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 void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxMiniFrame
*win
)
63 // don't need to install idle handler, its done from "event" signal
65 if (!win
->m_hasVMT
) return;
66 if (gdk_event
->count
> 0) return;
68 GtkPizza
*pizza
= GTK_PIZZA(widget
);
70 gtk_paint_shadow (widget
->style
,
74 NULL
, NULL
, NULL
, // FIXME: No clipping?
76 win
->m_width
, win
->m_height
);
78 int style
= win
->GetWindowStyle();
82 dc
.m_window
= pizza
->bin_window
;
84 if (style
& wxRESIZE_BORDER
)
86 dc
.SetBrush( *wxGREY_BRUSH
);
87 dc
.SetPen( *wxTRANSPARENT_PEN
);
88 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
91 if (!win
->GetTitle().empty() &&
92 ((style
& wxCAPTION
) ||
93 (style
& wxTINY_CAPTION_HORIZ
) ||
94 (style
& wxTINY_CAPTION_VERT
)))
96 dc
.SetFont( *wxSMALL_FONT
);
97 int height
= dc
.GetCharHeight();
99 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
100 dc
.SetBrush( brush
);
101 dc
.SetPen( *wxTRANSPARENT_PEN
);
102 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
);
104 dc
.SetTextForeground( *wxWHITE
);
105 dc
.DrawText( win
->GetTitle(), 6, 3 );
107 if (style
& wxCLOSE_BOX
)
108 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 2, true );
113 //-----------------------------------------------------------------------------
114 // "button_press_event" of m_mainWidget
115 //-----------------------------------------------------------------------------
118 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
120 // don't need to install idle handler, its done from "event" signal
122 if (!win
->m_hasVMT
) return FALSE
;
123 if (g_blockEventsOnDrag
) return TRUE
;
124 if (g_blockEventsOnScroll
) return TRUE
;
126 if (win
->m_isDragging
) return TRUE
;
128 GtkPizza
*pizza
= GTK_PIZZA(widget
);
129 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
131 int style
= win
->GetWindowStyle();
133 int y
= (int)gdk_event
->y
;
134 int x
= (int)gdk_event
->x
;
136 if ((style
& wxRESIZE_BORDER
) &&
137 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
139 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
141 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
145 gdk_window_get_origin( source
, &org_x
, &org_y
);
147 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
148 GDK_WINDOW_EDGE_SOUTH_EAST
,
157 if ((style
& wxCLOSE_BOX
) &&
158 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
160 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
168 dc
.SetFont( *wxSMALL_FONT
);
169 int height
= dc
.GetCharHeight() + 1;
172 if (y
> height
) return TRUE
;
174 gdk_window_raise( win
->m_widget
->window
);
176 gdk_pointer_grab( widget
->window
, FALSE
,
178 (GDK_BUTTON_PRESS_MASK
|
179 GDK_BUTTON_RELEASE_MASK
|
180 GDK_POINTER_MOTION_MASK
|
181 GDK_POINTER_MOTION_HINT_MASK
|
182 GDK_BUTTON_MOTION_MASK
|
183 GDK_BUTTON1_MOTION_MASK
),
186 (unsigned int) GDK_CURRENT_TIME
);
193 win
->m_isDragging
= true;
199 //-----------------------------------------------------------------------------
200 // "button_release_event" of m_mainWidget
201 //-----------------------------------------------------------------------------
204 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
206 // don't need to install idle handler, its done from "event" signal
208 if (!win
->m_hasVMT
) return FALSE
;
209 if (g_blockEventsOnDrag
) return TRUE
;
210 if (g_blockEventsOnScroll
) return TRUE
;
212 if (!win
->m_isDragging
) return TRUE
;
214 win
->m_isDragging
= false;
216 int x
= (int)gdk_event
->x
;
217 int y
= (int)gdk_event
->y
;
219 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
222 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
223 x
+= org_x
- win
->m_diffX
;
224 y
+= org_y
- win
->m_diffY
;
227 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
233 //-----------------------------------------------------------------------------
234 // "leave_notify_event" of m_mainWidget
235 //-----------------------------------------------------------------------------
239 gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxMiniFrame
*win
)
241 // don't need to install idle handler, its done from "event" signal
243 if (!win
->m_hasVMT
) return FALSE
;
244 if (g_blockEventsOnDrag
) return FALSE
;
246 gdk_window_set_cursor( widget
->window
, NULL
);
252 //-----------------------------------------------------------------------------
253 // "motion_notify_event" of m_mainWidget
254 //-----------------------------------------------------------------------------
258 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
260 // don't need to install idle handler, its done from "event" signal
262 if (!win
->m_hasVMT
) return FALSE
;
263 if (g_blockEventsOnDrag
) return TRUE
;
264 if (g_blockEventsOnScroll
) return TRUE
;
266 if (gdk_event
->is_hint
)
270 GdkModifierType state
;
271 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
274 gdk_event
->state
= state
;
277 int style
= win
->GetWindowStyle();
279 int x
= (int)gdk_event
->x
;
280 int y
= (int)gdk_event
->y
;
282 if (!win
->m_isDragging
)
284 if (style
& wxRESIZE_BORDER
)
286 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
287 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
289 gdk_window_set_cursor( widget
->window
, NULL
);
294 win
->m_oldX
= x
- win
->m_diffX
;
295 win
->m_oldY
= y
- win
->m_diffY
;
299 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
300 x
+= org_x
- win
->m_diffX
;
301 y
+= org_y
- win
->m_diffY
;
304 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
311 //-----------------------------------------------------------------------------
313 //-----------------------------------------------------------------------------
315 static unsigned char close_bits
[]={
316 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
317 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
318 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
321 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
323 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
324 const wxPoint
&pos
, const wxSize
&size
,
325 long style
, const wxString
&name
)
327 style
= style
| wxCAPTION
;
329 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
332 if (style
& wxRESIZE_BORDER
)
336 m_isDragging
= false;
342 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
344 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
346 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
349 if ((style
& wxCLOSE_BOX
) &&
350 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
352 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
353 img
.Replace(0,0,0,123,123,123);
354 img
.SetMaskColour(123,123,123);
355 m_closeButton
= wxBitmap( img
);
358 /* these are called when the borders are drawn */
359 g_signal_connect (m_mainWidget
, "expose_event",
360 G_CALLBACK (gtk_window_own_expose_callback
), this );
362 /* these are required for dragging the mini frame around */
363 g_signal_connect (m_mainWidget
, "button_press_event",
364 G_CALLBACK (gtk_window_button_press_callback
), this);
365 g_signal_connect (m_mainWidget
, "button_release_event",
366 G_CALLBACK (gtk_window_button_release_callback
), this);
367 g_signal_connect (m_mainWidget
, "motion_notify_event",
368 G_CALLBACK (gtk_window_motion_notify_callback
), this);
369 g_signal_connect (m_mainWidget
, "leave_notify_event",
370 G_CALLBACK (gtk_window_leave_callback
), this);
374 void wxMiniFrame::SetTitle( const wxString
&title
)
376 wxFrame::SetTitle( title
);
378 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
379 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
382 #endif // wxUSE_MINIFRAME