Strip off version numbers from dir name
[dockapps.git] / wmnotify / src / xevents.c
blob976aaad5e2678951063d5a2f1f22a6f7a80a98f8
1 /*
2 * xevents.c -- handling X events, and detecting single-click and double-click
3 * mouse events.
5 * Copyright (C) 2009 Hugo Villeneuve <hugo@hugovil.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <time.h>
33 #include <pthread.h>
34 #include <sys/types.h>
35 #include <X11/Xlib.h>
37 #include "common.h"
38 #include "dockapp.h"
39 #include "xevents.h"
42 /* Maximum time between mouse double-clicks, in milliseconds */
43 #define DOUBLE_CLICK_MAX_INTERVAL_MS 250
46 /* Function pointers to handle single and double mouse click events. */
47 static void (*SingleClickCallback)( void ) = NULL;
49 static void (*DoubleClickCallback)( void ) = NULL;
52 void
53 AudibleBeep( void )
55 /* The specified volume is relative to the base volume for the keyboard.
56 To change the base volume of the keyboard, use XChangeKeyboardControl(). */
57 (void) XBell( dockapp.display, 100 ); /* Volume = 100% */
61 /* This function must be called at the beginning of your program to initialize
62 the function pointers to handle single and double click mouse events. */
63 void
64 ProcessXlibEventsInit( void (*single_click_callback)( void ),
65 void (*double_click_callback)( void ) )
67 int status;
69 /* This must be called before any other XLib functions. */
70 status = XInitThreads();
71 if( status == 0 ) {
72 fprintf( stderr, "%s: XInitThreads() initialization failed\n", PACKAGE );
73 ErrorLocation( __FILE__, __LINE__ );
74 exit( EXIT_FAILURE );
77 SingleClickCallback = single_click_callback;
78 DoubleClickCallback = double_click_callback;
82 /* Processing of X events */
83 void
84 ProcessXlibEvents( void )
86 bool quit = false;
87 bool button1_pressed = false;
88 bool check_for_double_click = false;
89 XEvent Event;
91 while( quit == false ) {
92 if( ( check_for_double_click != false ) &&
93 ( XPending( dockapp.display ) == 0 ) ) {
94 /* If no other button 1 events are received after the delay, then it is a
95 single-click mouse event. */
96 if( SingleClickCallback != NULL ) {
97 (*SingleClickCallback)();
100 check_for_double_click = false;
102 /* XNextEvent is a blocking call: it will return only when an event is
103 ready to be processed, thus freeing the CPU for other tasks when no
104 events are available. */
105 (void) XNextEvent( dockapp.display, &Event );
106 switch( Event.type ) {
107 case Expose:
108 /* Window was uncovered... */
109 RedrawWindow();
110 break;
111 case DestroyNotify:
112 /* Window was killed... */
113 /* Is this necessary ? */
114 (void) XCloseDisplay( dockapp.display );
115 quit = true;
116 break;
117 case ClientMessage:
118 /* Doesn't seem to work... */
119 printf( "Client message received...\n" );
120 break;
121 case ButtonPress:
122 if( Event.xbutton.button == Button1 ) {
123 /* Mouse LEFT button pressed. */
124 button1_pressed = true;
126 break;
127 case ButtonRelease:
128 if( Event.xbutton.button == Button1 ) {
129 /* Mouse LEFT button released. */
130 if( button1_pressed != false ) {
131 /* We act only when the button is released */
132 if( check_for_double_click != false ) {
133 /* Double-click */
134 if( DoubleClickCallback != NULL ) {
135 (*DoubleClickCallback)();
137 check_for_double_click = false;
139 else {
140 (void) usleep( DOUBLE_CLICK_MAX_INTERVAL_MS * 1000 );
141 check_for_double_click = true;
145 break;
147 } /* end while */