4 * Part of gwm, the Gratuitous Window Manager,
5 * by Gary Wong, <gtw@gnu.org>.
7 * Copyright (C) 2009 Gary Wong
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of version 3 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include "window-table.h"
34 #define BUTTON_SIZE 12 /* size of buttons in title bar; excludes X border */
35 #define BUTTON_X_BORDER 1
37 extern int button_size( struct gwm_window
*window
, int include_x_border
) {
39 assert( window
->type
== WINDOW_BUTTON
);
41 return BUTTON_SIZE
+ ( include_x_border
? BUTTON_X_BORDER
<< 1 : 0 );
44 extern int button_xb( struct gwm_window
*window
) {
46 assert( window
->type
== WINDOW_BUTTON
);
48 return BUTTON_X_BORDER
;
51 static int button_active
;
53 static void set_button_active( struct gwm_window
*window
, int new ) {
57 if( new == button_active
)
60 n
= gwm_screens
[ window
->screen
].pixels
[ ( button_active
= new ) ?
62 COL_BUTTON_INACTIVE
];
63 xcb_change_window_attributes( c
, window
->w
, XCB_CW_BACK_PIXEL
, &n
);
65 queue_window_update( window
, 0, 0, button_size( window
, FALSE
),
66 button_size( window
, FALSE
), FALSE
);
69 static void button_button_press( struct gwm_window
*window
,
70 xcb_button_press_event_t
*ev
) {
72 if( !pointer_demux
) {
74 pointer_demux
= window
->w
;
76 set_button_active( window
, TRUE
);
79 if( ( window
->u
.button
.frame
->u
.frame
.child
->u
.managed
.protocols
&
80 PROTOCOL_DELETE_WINDOW
) && ( ev
->detail
== 3 ||
81 ( ev
->state
& XCB_BUTTON_MASK_3
) ) )
82 /* Button 3 will kill the client, even if it supports WM_DELETE_WINDOW.
83 Change to CURSOR_DESTROY to indicate the distinction. */
84 xcb_change_active_pointer_grab( c
, cursors
[ CURSOR_DESTROY
],
85 ev
->time
, XCB_EVENT_MASK_BUTTON_PRESS
|
86 XCB_EVENT_MASK_BUTTON_RELEASE
|
87 XCB_EVENT_MASK_ENTER_WINDOW
|
88 XCB_EVENT_MASK_LEAVE_WINDOW
);
91 static void button_button_release( struct gwm_window
*window
,
92 xcb_button_release_event_t
*ev
) {
97 if( final_release( ev
) ) {
98 /* Final button released; grab terminates. */
100 if( ev
->detail
== 3 || !( window
->u
.button
.frame
->u
.frame
.child
->
101 u
.managed
.protocols
&
102 PROTOCOL_DELETE_WINDOW
) )
103 xcb_kill_client( c
, window
->u
.button
.frame
->u
.frame
.child
->w
);
105 xcb_client_message_event_t msg
;
106 struct gwm_window
*frame
= window
->u
.button
.frame
;
108 msg
.response_type
= XCB_CLIENT_MESSAGE
;
111 msg
.window
= frame
->u
.frame
.child
->w
;
112 msg
.type
= atoms
[ ATOM_WM_PROTOCOLS
];
113 msg
.data
.data32
[ 0 ] = atoms
[ ATOM_WM_DELETE_WINDOW
];
114 msg
.data
.data32
[ 1 ] = ev
->time
;
115 msg
.data
.data32
[ 2 ] = 0;
116 msg
.data
.data32
[ 3 ] = 0;
117 msg
.data
.data32
[ 4 ] = 0;
119 xcb_send_event( c
, FALSE
, frame
->u
.frame
.child
->w
, 0,
123 set_button_active( window
, FALSE
);
126 pointer_demux
= XCB_NONE
;
127 } else if( ev
->detail
== 3 && ( window
->u
.button
.frame
->u
.frame
.child
->
128 u
.managed
.protocols
&
129 PROTOCOL_DELETE_WINDOW
) )
130 /* Button 3 released; we'll no longer kill the client. Remove
131 the temporary CURSOR_DESTROY. */
132 xcb_change_active_pointer_grab( c
, XCB_NONE
, ev
->time
,
133 XCB_EVENT_MASK_BUTTON_PRESS
|
134 XCB_EVENT_MASK_BUTTON_RELEASE
|
135 XCB_EVENT_MASK_ENTER_WINDOW
|
136 XCB_EVENT_MASK_LEAVE_WINDOW
);
139 static void button_enter_notify( struct gwm_window
*window
,
140 xcb_enter_notify_event_t
*ev
) {
145 if( ev
->event
== window
->w
)
146 set_button_active( window
, TRUE
);
149 static void button_leave_notify( struct gwm_window
*window
,
150 xcb_leave_notify_event_t
*ev
) {
155 if( ev
->event
== window
->w
)
156 set_button_active( window
, FALSE
);
159 const event_handler button_handlers
[ NUM_EXTENDED_EVENTS
] = {
163 NULL
, /* KeyRelease */
164 (event_handler
) button_button_press
,
165 (event_handler
) button_button_release
,
166 NULL
, /* MotionNotify */
167 (event_handler
) button_enter_notify
,
168 (event_handler
) button_leave_notify
,
171 NULL
, /* KeymapNotify */
173 NULL
, /* GraphicsExpose */
174 NULL
, /* NoExposure */
175 NULL
, /* VisibilityNotify */
176 NULL
, /* CreateNotify */
177 NULL
, /* DestroyNotify */
178 NULL
, /* UnmapNotify */
179 NULL
, /* MapNotify */
180 NULL
, /* MapRequest */
181 NULL
, /* ReparentNotify */
182 NULL
, /* ConfigureNotify */
183 NULL
, /* ConfigureRequest */
184 NULL
, /* GravityNotify */
185 NULL
, /* ResizeRequest */
186 NULL
, /* CirculateNotify */
187 NULL
, /* CirculateRequest */
188 NULL
, /* PropertyNotify */
189 NULL
, /* SelectionClear */
190 NULL
, /* SelectionRequest */
191 NULL
, /* SelectionNotify */
192 NULL
, /* ColormapNotify */
193 NULL
, /* ClientMessage */
194 NULL
, /* MappingNotify */
195 NULL
, /* (synthetic) */
196 NULL
, /* RRScreenChangeNotify */
197 NULL
/* ShapeNotify */