wmail: use continue instead of goto.
[dockapps.git] / wmressel / src / wmressel.c
blob90a8c8c61abc10b9ae4eae26603cab7957381d1c
1 /*
3 wmressel.c
4 X11 resolution selector (for Window Maker)
5 by Sébastien "Slix" Liénard <slix@gcu-squad.org>, GCU Squad (http://gcu-squad.org)
6 based on gvidm and wmtimer
7 and licensed through the GNU General Public License.
9 Read the COPYING file for the complete GNU license.
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <time.h>
16 #include <string.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <ctype.h>
20 #include <sys/utsname.h>
22 #include <X11/Xlib.h>
23 #include <X11/xpm.h>
24 #include <X11/extensions/shape.h>
25 #include <X11/extensions/xf86vmode.h>
27 #define V_PHSYNC 0x001
28 #define V_NHSYNC 0x002
29 #define V_PVSYNC 0x004
30 #define V_NVSYNC 0x008
31 #define V_INTERLACE 0x010
32 #define V_DBLSCAN 0x020
33 #define V_CSYNC 0x040
34 #define V_PCSYNC 0x080
35 #define V_NCSYNC 0x100
37 #ifdef HAVE_LIBXINERAMA
38 #include <X11/extensions/Xinerama.h>
39 #endif
41 #include <gtk/gtk.h>
43 #include <libdockapp/wmgeneral.h>
44 #include <libdockapp/misc.h>
46 #include "wmressel-master.xpm"
47 #include "wmressel-mask.xbm"
49 #define MY_EMAIL "slix@gcu-squad.org"
50 #define GCU_HOME "http://gcu-squad.org/"
52 typedef struct {
53 int screen;
54 int mode;
55 } MENU_CHOICE;
57 void usage(void);
58 void printVersion(void);
59 void BlitString(char *name, int x, int y);
60 void BlitNum(int num, int x, int y);
61 void wmressel_routine(int, char **, int);
62 void MenuEvent (GtkWidget *, gpointer);
63 void on_deactivate(void);
64 void create_popup(int);
65 GtkWidget *create_screen_submenu (int);
66 char *create_submenu_label(XF86VidModeModeInfo *, XF86VidModeModeLine, int);
67 void update_res_display(int);
68 void show_screen_number(int);
69 int get_screen_count(void);
71 char *ProgName;
72 int show_refresh_rate=0;
73 int show_doublescan=0;
74 int show_only_selected=0;
76 int main(int argc, char *argv[])
79 int i, selected_screen=0;
80 char *endp=NULL;
82 /* Parse Command Line */
84 ProgName = argv[0];
85 if (strlen(ProgName) >= 5)
86 ProgName += (strlen(ProgName) - 5);
88 for (i=1; i<argc; i++) {
89 char *arg = argv[i];
91 if (*arg=='-') {
92 switch (arg[1]) {
93 case '-' :
94 /* wmgeneral.c has been modified to allow this trick: openXwindow and gtk_init */
95 /* use same option (--display) for display setting */
96 if (strcmp(arg+1, "-display")) {
97 usage();
98 exit(1);
100 break;
101 case 'd' :
102 show_doublescan=1;
103 break;
104 case 'r' :
105 show_refresh_rate=1;
106 break;
107 case 'o' :
108 show_only_selected=1;
109 break;
110 case 's' :
111 if (++i==argc) {
112 usage();
113 exit(1);
115 selected_screen = strtol(argv[i], &endp, 10);
116 if (*endp) {
117 usage();
118 exit(1);
120 break;
121 case 'v' :
122 printVersion();
123 exit(0);
124 break;
125 default:
126 usage();
127 exit(0);
128 break;
133 wmressel_routine(argc, argv, selected_screen);
134 return(0);
137 /*******************
138 * wmressel_routine *
139 *******************/
141 void wmressel_routine(int argc, char **argv, int selected_screen)
143 int i, but_stat=-1;
144 XEvent Event;
146 int j=0, show_number=0, screen_count;
148 openXwindow(argc, argv, wmressel_master_xpm, wmressel_mask_bits, wmressel_mask_width, wmressel_mask_height);
150 screen_count = get_screen_count();
151 if (selected_screen > screen_count-1) {
152 printf("\nScreen number %i is not valid !!!\n", selected_screen);
153 usage();
154 exit(1);
157 if (screen_count > 1) {
158 show_screen_number(selected_screen);
159 show_number=1;
160 } else {
161 update_res_display(selected_screen);
164 AddMouseRegion( 0, 5, 5, 55, 55);
166 gtk_init (&argc, &argv);
168 while (1) {
169 /* X Events */
170 while (XPending(display)) {
171 XNextEvent(display, &Event);
172 switch (Event.type) {
173 case Expose:
174 RedrawWindow();
175 break;
176 case DestroyNotify:
177 XCloseDisplay(display);
178 exit(0);
179 break;
180 case ButtonPress:
181 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
182 but_stat = i;
183 break;
184 case ButtonRelease:
185 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
186 if (but_stat == i && but_stat >= 0) {
188 screen_count=get_screen_count();
190 if(Event.xbutton.button==1) {
191 /* Left button pressed, popup menu */
192 create_popup(selected_screen);
193 gtk_main();
194 update_res_display(selected_screen);
196 } else if (Event.xbutton.button==3 && screen_count>1) {
197 /* Right button pressed, view screen number */
198 show_screen_number(selected_screen);
199 show_number=1;
201 } else if (Event.xbutton.button==4 && screen_count>1) {
202 /* Mouse wheel up, select next screen */
203 if(selected_screen==get_screen_count()-1) {
204 selected_screen=0;
205 } else {
206 selected_screen++;
208 show_screen_number(selected_screen);
209 show_number=1;
211 } else if (Event.xbutton.button==5 && screen_count>1) {
212 /* Mouse wheel down, select previous screen */
213 if(selected_screen==0) {
214 selected_screen=get_screen_count()-1;
215 } else {
216 selected_screen--;
218 show_screen_number(selected_screen);
219 show_number=1;
222 but_stat = -1;
223 break;
226 if(show_number) {
227 j++;
228 if (j==10) {
229 update_res_display(selected_screen);
230 show_number=0;
231 j=0;
234 usleep(100000L);
238 /********************
239 * Create popup menu *
240 ********************/
241 void create_popup(int selected_screen)
244 GtkWidget *menu_ptr;
246 int i;
247 char label_str[14];
248 GtkWidget *submenu_ptr, *menuitem_ptr;
249 int screen_count = get_screen_count();
251 if (screen_count > 1 && !show_only_selected) {
252 menu_ptr = gtk_menu_new();
253 for (i=0; i<screen_count; i++) {
254 submenu_ptr = create_screen_submenu(0);
255 sprintf(label_str, "Screen %i",i);
256 menuitem_ptr = gtk_menu_item_new_with_label(label_str);
257 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuitem_ptr), submenu_ptr);
258 gtk_menu_shell_append(GTK_MENU_SHELL (menu_ptr), menuitem_ptr);
259 gtk_widget_show(menuitem_ptr);
260 gtk_widget_show(submenu_ptr);
262 } else {
263 menu_ptr = create_screen_submenu(selected_screen);
266 g_signal_connect (G_OBJECT (menu_ptr), "deactivate", G_CALLBACK (on_deactivate), NULL);
267 /* gtk_menu_popup() is deprecated, but we need a GdkWindow to
268 use any of its replacements, so keeping for now */
269 gtk_menu_popup(GTK_MENU(menu_ptr), NULL, NULL, NULL, NULL, 0, 0);
272 /************************************************
273 * Procede GTK menu choice and switch resolution *
274 ************************************************/
275 void MenuEvent (GtkWidget *widget, gpointer menu_choice) {
276 XF86VidModeModeInfo **vm_modelines;
277 int vm_count;
279 XF86VidModeGetAllModeLines(display, ((MENU_CHOICE *)menu_choice)->screen, &vm_count, &vm_modelines);
280 XF86VidModeSwitchToMode(display, ((MENU_CHOICE *)menu_choice)->screen, vm_modelines[((MENU_CHOICE *)menu_choice)->mode]);
281 XFlush(display);
282 free(vm_modelines);
285 /***************************
286 * Return number of screens *
287 ***************************/
288 int get_screen_count()
290 int screen_count;
291 #ifdef HAVE_LIBXINERAMA
292 int i;
293 int screen_exists[1024];
294 XineramaScreenInfo *screen;
296 if (XineramaIsActive(display)) {
297 screen = XineramaQueryScreens(display, screen_exists);
298 for (i=0; i==screen[i].screen_number; i++){}
299 screen_count=i;
300 XFree(screen);
301 } else {
302 #endif
303 screen_count = XScreenCount(display);
304 #ifdef HAVE_LIBXINERAMA
306 #endif
307 return(screen_count);
310 void on_deactivate(void) {
311 gtk_main_quit();
314 /*********************************
315 * Create a label for a menu item *
316 **********************************/
317 char *create_submenu_label(XF86VidModeModeInfo *modeline, XF86VidModeModeLine current, int dotclock)
319 char *label_str;
320 char def[3], res[12];
321 char rr[8]="";
322 char ds[3]="";
324 label_str = malloc(sizeof(def)+sizeof(res)+sizeof(rr)+sizeof(ds)-3);
326 if ((current.hdisplay==modeline->hdisplay) && (current.vdisplay==modeline->vdisplay) && (dotclock==modeline->dotclock)) {
327 sprintf(def, "* ");
328 } else {
329 sprintf(def, " ");
332 sprintf(res, "%ix%i", modeline->hdisplay, modeline->vdisplay);
334 if (show_refresh_rate) {
335 if ((modeline->flags) & V_DBLSCAN) {
336 sprintf(rr, "@%iHz", modeline->dotclock*500/(modeline->htotal*modeline->vtotal));
337 } else {
338 sprintf(rr, "@%iHz", modeline->dotclock*1000/(modeline->htotal*modeline->vtotal));
342 if (show_doublescan && ((modeline->flags) & V_DBLSCAN)) sprintf (ds, " D");
344 sprintf(label_str, "%s%s%s%s", def, res, rr, ds);
345 return (label_str);
348 /*******************************************************
349 * Create menu composed of available modes for a screen *
350 *******************************************************/
351 GtkWidget *create_screen_submenu (int screen)
353 int i, dotclock, vm_count=0;
354 MENU_CHOICE *menu_choice;
355 char *label_str;
356 GtkWidget *menuitem_ptr, *menu_ptr;
357 XF86VidModeModeInfo **vm_modelines;
358 XF86VidModeModeLine modeline;
360 XF86VidModeGetAllModeLines(display, screen, &vm_count, &vm_modelines);
361 XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
363 menu_ptr = gtk_menu_new();
365 for (i=0; i<vm_count; i++) {
367 label_str = create_submenu_label(vm_modelines[i], modeline, dotclock);
369 menu_choice = malloc(sizeof(menu_choice));
370 menu_choice->screen=screen;
371 menu_choice->mode=i;
373 menuitem_ptr = gtk_menu_item_new_with_label(label_str);
374 g_signal_connect(G_OBJECT (menuitem_ptr), "activate", G_CALLBACK (MenuEvent), (gpointer)menu_choice);
375 gtk_menu_shell_append(GTK_MENU_SHELL (menu_ptr), menuitem_ptr);
376 gtk_widget_show(menuitem_ptr);
377 free(label_str);
380 free(vm_modelines);
382 return(menu_ptr);
385 /******************************************
386 * Update displayed resolution information *
387 ******************************************/
388 void update_res_display(int screen)
390 int dotclock;
391 XF86VidModeModeLine modeline;
392 XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
394 /* Clear screen zone */
395 copyXPMArea(76, 12, 35, 29, 14, 13);
397 /* Show resolution */
398 BlitNum(modeline.hdisplay, 41, 14);
399 BlitString("X", 15, 23);
400 BlitNum(modeline.vdisplay, 41, 23);
402 /* Show frequency */
403 if ((modeline.flags) & V_DBLSCAN) {
404 BlitNum(dotclock*500/(modeline.htotal*modeline.vtotal), 29, 32);
405 } else {
406 BlitNum(dotclock*1000/(modeline.htotal*modeline.vtotal), 29, 32);
408 BlitString("Hz", 35, 32);
410 RedrawWindow();
413 /*****************************
414 * Show screen number (SCR X) *
415 *****************************/
416 void show_screen_number(int screen)
418 /* Clear screen zone */
419 copyXPMArea(76, 12, 35, 29, 14, 13);
421 BlitString("Scr", 15, 23);
422 BlitNum(screen, 41, 23);
423 RedrawWindow();
426 /* Blits a string at given co-ordinates */
427 void BlitString(char *name, int x, int y)
429 int i;
430 int c;
431 int k;
433 k = x;
434 for (i=0; name[i]; i++) {
435 c = toupper(name[i]);
436 if (c >= 'A' && c <= 'Z')
437 { /* its a letter */
438 c -= 'A';
439 copyXPMArea(c * 6, 74, 6, 8, k, y);
440 k += 6;
442 else
443 { /* its a number or symbol */
444 c -= '0';
445 copyXPMArea(c * 6, 64, 6, 8, k, y);
446 k += 6;
452 /* Blits number to give coordinates.. nine 0's, right justified */
454 void BlitNum(int num, int x, int y)
456 char buf[1024];
457 int newx=x;
459 if ( num > 9 ) newx -= 6;
460 if ( num > 99 ) newx -= 6;
461 if ( num > 999 ) newx -= 6;
462 if ( num > 9999 ) newx -= 6;
464 sprintf(buf, "%i", num);
466 BlitString(buf, newx, y);
469 /*******************************************************************************\
470 |* usage *|
471 \*******************************************************************************/
473 void usage(void)
475 printf ("\n wmressel version %s -- X11 resolution selector for Window Maker\n", PACKAGE_VERSION );
476 printf (" Copyright (C) 2002 Sébastien Liénard <%s>\n", MY_EMAIL);
477 printf (" from GCU (%s)\n",GCU_HOME);
478 printf (" This software comes with NO WARRANTY.\n\n");
479 printf ("usage:\n");
480 printf ("\t-r\t\t\tShow refresh rates in menu\n");
481 printf ("\t-d\t\t\tShow in menu if a mode is a Doublescan mode (D)\n");
482 printf ("\t-s <number>\t\tShow information about this screen\n");
483 printf ("\t-o\t\t\tOnly show menu for selected screen\n");
484 printf ("\t--display <display>\tSet display\n");
485 printf ("\t-h\t\t\tthis help screen\n");
486 printf ("\t-v\t\t\tprint the version number\n");
487 printf ("\n");
490 /*******************************************************************************\
491 |* printVersion *|
492 \*******************************************************************************/
494 void printVersion(void) {
495 fprintf(stderr, "wmressel v%s\n", PACKAGE_VERSION);