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();
81 wxImplDC
*impl
= dc
.GetImpl();
82 wxGTKClientImplDC
*client_impl
= wxDynamicCast( impl
, wxGTKClientImplDC
);
84 client_impl
->m_window
= pizza
->bin_window
;
87 dc
.m_window
= pizza
->bin_window
;
90 if (style
& wxRESIZE_BORDER
)
92 dc
.SetBrush( *wxGREY_BRUSH
);
93 dc
.SetPen( *wxTRANSPARENT_PEN
);
94 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
97 if (!win
->GetTitle().empty() &&
98 ((style
& wxCAPTION
) ||
99 (style
& wxTINY_CAPTION_HORIZ
) ||
100 (style
& wxTINY_CAPTION_VERT
)))
102 dc
.SetFont( *wxSMALL_FONT
);
103 int height
= dc
.GetCharHeight();
105 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
106 dc
.SetBrush( brush
);
107 dc
.SetPen( *wxTRANSPARENT_PEN
);
108 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
);
110 dc
.SetTextForeground( *wxWHITE
);
111 dc
.DrawText( win
->GetTitle(), 6, 3 );
113 if (style
& wxCLOSE_BOX
)
114 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 2, true );
120 //-----------------------------------------------------------------------------
121 // "button_press_event" of m_mainWidget
122 //-----------------------------------------------------------------------------
125 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
127 if (!win
->m_hasVMT
) return FALSE
;
128 if (g_blockEventsOnDrag
) return TRUE
;
129 if (g_blockEventsOnScroll
) return TRUE
;
131 if (win
->m_isDragging
) return TRUE
;
133 GtkPizza
*pizza
= GTK_PIZZA(widget
);
134 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
136 int style
= win
->GetWindowStyle();
138 int y
= (int)gdk_event
->y
;
139 int x
= (int)gdk_event
->x
;
141 if ((style
& wxRESIZE_BORDER
) &&
142 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
144 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
146 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
150 gdk_window_get_origin( source
, &org_x
, &org_y
);
152 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
153 GDK_WINDOW_EDGE_SOUTH_EAST
,
162 if ((style
& wxCLOSE_BOX
) &&
163 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
165 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
173 dc
.SetFont( *wxSMALL_FONT
);
174 int height
= dc
.GetCharHeight() + 1;
177 if (y
> height
) return TRUE
;
179 gdk_window_raise( win
->m_widget
->window
);
181 gdk_pointer_grab( widget
->window
, FALSE
,
183 (GDK_BUTTON_PRESS_MASK
|
184 GDK_BUTTON_RELEASE_MASK
|
185 GDK_POINTER_MOTION_MASK
|
186 GDK_POINTER_MOTION_HINT_MASK
|
187 GDK_BUTTON_MOTION_MASK
|
188 GDK_BUTTON1_MOTION_MASK
),
191 (unsigned int) GDK_CURRENT_TIME
);
198 win
->m_isDragging
= true;
204 //-----------------------------------------------------------------------------
205 // "button_release_event" of m_mainWidget
206 //-----------------------------------------------------------------------------
209 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
211 if (!win
->m_hasVMT
) return FALSE
;
212 if (g_blockEventsOnDrag
) return TRUE
;
213 if (g_blockEventsOnScroll
) return TRUE
;
215 if (!win
->m_isDragging
) return TRUE
;
217 win
->m_isDragging
= false;
219 int x
= (int)gdk_event
->x
;
220 int y
= (int)gdk_event
->y
;
222 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
225 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
226 x
+= org_x
- win
->m_diffX
;
227 y
+= org_y
- win
->m_diffY
;
230 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
236 //-----------------------------------------------------------------------------
237 // "leave_notify_event" of m_mainWidget
238 //-----------------------------------------------------------------------------
242 gtk_window_leave_callback(GtkWidget
*widget
,
243 GdkEventCrossing
* WXUNUSED(gdk_event
),
246 if (!win
->m_hasVMT
) return FALSE
;
247 if (g_blockEventsOnDrag
) return FALSE
;
249 gdk_window_set_cursor( widget
->window
, NULL
);
255 //-----------------------------------------------------------------------------
256 // "motion_notify_event" of m_mainWidget
257 //-----------------------------------------------------------------------------
261 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
263 if (!win
->m_hasVMT
) return FALSE
;
264 if (g_blockEventsOnDrag
) return TRUE
;
265 if (g_blockEventsOnScroll
) return TRUE
;
267 if (gdk_event
->is_hint
)
271 GdkModifierType state
;
272 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
275 gdk_event
->state
= state
;
278 int style
= win
->GetWindowStyle();
280 int x
= (int)gdk_event
->x
;
281 int y
= (int)gdk_event
->y
;
283 if (!win
->m_isDragging
)
285 if (style
& wxRESIZE_BORDER
)
287 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
288 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
290 gdk_window_set_cursor( widget
->window
, NULL
);
295 win
->m_oldX
= x
- win
->m_diffX
;
296 win
->m_oldY
= y
- win
->m_diffY
;
300 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
301 x
+= org_x
- win
->m_diffX
;
302 y
+= org_y
- win
->m_diffY
;
305 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
312 //-----------------------------------------------------------------------------
314 //-----------------------------------------------------------------------------
316 static unsigned char close_bits
[]={
317 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
318 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
319 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
322 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
324 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
325 const wxPoint
&pos
, const wxSize
&size
,
326 long style
, const wxString
&name
)
328 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
331 if (style
& wxRESIZE_BORDER
)
335 m_isDragging
= false;
341 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
343 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
345 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
348 if ((style
& wxCLOSE_BOX
) &&
349 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
351 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
352 img
.Replace(0,0,0,123,123,123);
353 img
.SetMaskColour(123,123,123);
354 m_closeButton
= wxBitmap( img
);
357 /* these are called when the borders are drawn */
358 g_signal_connect (m_mainWidget
, "expose_event",
359 G_CALLBACK (gtk_window_own_expose_callback
), this );
361 /* these are required for dragging the mini frame around */
362 g_signal_connect (m_mainWidget
, "button_press_event",
363 G_CALLBACK (gtk_window_button_press_callback
), this);
364 g_signal_connect (m_mainWidget
, "button_release_event",
365 G_CALLBACK (gtk_window_button_release_callback
), this);
366 g_signal_connect (m_mainWidget
, "motion_notify_event",
367 G_CALLBACK (gtk_window_motion_notify_callback
), this);
368 g_signal_connect (m_mainWidget
, "leave_notify_event",
369 G_CALLBACK (gtk_window_leave_callback
), this);
373 void wxMiniFrame::SetTitle( const wxString
&title
)
375 wxFrame::SetTitle( title
);
377 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
378 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
381 #endif // wxUSE_MINIFRAME